2

I was using character arrays to get inputs from the user then display the output afterwards. However, every time I enter values with spaces in between, only the first word before the space is printed.

For instance, this is what I typed:

Customer No.: 7877 323 2332

This will be the output:

Customer No.: 7877

I already searched for possible solutions but I can't seem to find the right solution.

This is my code for reference:

#include<iostream>
using namespace std;

int main()
{
    char custNum[10] = " ";  // The assignment does not allow std::string
    
    cout << "Please enter values for the following: " << endl;
    cout << "Customer No.: ";
    cin >> custNum;
    
    cout << "Customer No.: " << custNum << endl;
}
JaMiT
  • 9,693
  • 2
  • 12
  • 26
Quinton417
  • 23
  • 5
  • Any particular reason for not using std::string? – kesarling Sep 02 '20 at 03:10
  • @d4rk4ng31, we were asked not to use it for the meantime. It would be much easier if we could. – Quinton417 Sep 02 '20 at 03:12
  • Hmm.... Okay, anyways, try using `char* str = new char[1];` `scanf("%[^\n]s",str);` instead – kesarling Sep 02 '20 at 03:19
  • 1
    Don't SKIMP on buffer size (e.g. `char custNum[32]`) to read the line as a string requires a minimum of `14` characters (double that and take the next power-of-two for a rough hack) – David C. Rankin Sep 02 '20 at 04:23
  • Does this answer your question? [Reading string from input with space character?](https://stackoverflow.com/questions/6282198/reading-string-from-input-with-space-character) – kesarling Sep 02 '20 at 09:24

3 Answers3

2

Another option is to use std::basic_istream::getline to read the entire string into the buffer and then remove the spaces with a simple for loop. But when using plain-old character arrays don't skimp on buffer size. It is far better to be 1000-characters too long than one-character too short. With your input, your absolute minimum size of custNum is 14 characters (the 13 shown plus the '\0' (nul-terminating) character. (rough rule-of-thumb, take your longest estimated input and double it -- to allow for user-mistake, cat stepping on keyboard, etc...)

In you case you can simply do:

#include <iostream>
#include <cctype>

int main() {
    
    char custNum[32] = " ";  // The assignment does not allow std::string
    int wrt = 0;
    
    std::cout << "Please enter values for the following:\nCustomer No.: ";
    
    if (std::cin.getline(custNum, 32)) {    /* validate every input */
    
        for (int rd = 0; custNum[rd]; rd++)
            if (!isspace((unsigned char)custNum[rd]))
                custNum[wrt++] = custNum[rd];
        custNum[wrt] = 0;
        
        std::cout << "Customer No.: " << custNum << '\n';
    }
}

The two loop counters rd (read position) and wrt (write position) are simply used to loop over the original string and remove any whitespace found, nul-terminating again when the loop is left.

Example Use/Output

$ ./bin/readcustnum
Please enter values for the following:
Customer No.: 7877 323 2332
Customer No.: 78773232332

Also take a look at Why is “using namespace std;” considered bad practice? and C++: “std::endl” vs “\n”. Much easier to build good habits now than it is to break bad ones later... Look things over and let me know if you have questions.

David C. Rankin
  • 69,681
  • 6
  • 44
  • 72
1

Apart from std::getline, if you are going to use C-style strings, try the following code:

int main() {
    char* str = new char[60];
    scanf("%[^\n]s", str);  //accepts space a a part of the string (does not give UB as it may seem initially
    printf("%s", str);
    return 0;
}

Also, if you absolutely need it to be a number, then use atoi

int ivar = std::atoi(str);

PS Not to forget gets (!!dangerous!!)

char* str;
gets(str);
puts(str);
kesarling
  • 1,745
  • 2
  • 7
  • 27
  • Now about that misplaced `'s'`? `:)` [man 3 scanf](https://www.man7.org/linux/man-pages/man3/scanf.3.html) or [C11 Standard - 7.21.6.2 The fscanf function(p12)](http://port70.net/~nsz/c/c11/n1570.html#7.21.6.2p12) – David C. Rankin Sep 02 '20 at 05:17
  • @DavidC.Rankin Seriously man. Now you are just picking on me :( https://stackoverflow.com/a/6282396 – kesarling Sep 02 '20 at 08:58
  • @Quinton417, do not forget to click that little check mark and accept the answer which worked for you – kesarling Sep 02 '20 at 09:24
  • Also, do take a look at @DavidC.Rankin's answer as well. It is better than mine :) – kesarling Sep 02 '20 at 09:25
  • Thank you. And I presume you are referring to the comment below the answer you link to above? The `'s'` as you have it will seek to match a literal `'s'` in the input, but since no conversion follows and since a prior successful conversion took place, no *matching failure* or *input failure* results. What it will do is prevent any subsequent conversion specifier from matching. Try and match `scanf("%[^\n]s%d", str, &i)` and then `scanf("%[^\n]%d", str, &i)` (multi-line input required) – David C. Rankin Sep 02 '20 at 20:49
0

cin >> int_variable will stop reading input when it reaches the first character that isn't a valid part of a number. C++ does not consider spaces part of a number, so it stops reading as soon as it encounters one.

You could use std::getline to read into a string instead, then remove the spaces from the string before converting to an integer. Or maybe in this case you don't even need the integer and can leave it as a string.

Mark Ransom
  • 271,357
  • 39
  • 345
  • 578
  • The OP is not reading an `int` variable. While it is called "custNum", the declared type is an array of `char`. I think the intent is to store a formatted number (keeping the spaces). – JaMiT Sep 02 '20 at 04:48
  • @JaMiT the definition of `custNum` was edited into the question, I had to guess when I first saw it. – Mark Ransom Sep 02 '20 at 14:29
  • More precisely, it was restored to the question, but true, it was gone for a while (less than an hour -- in fact it was restored just before you posted this answer). That is why I posted a gentle nudge instead of saying you failed to answer the question. Besides, it would take just a few tweaks to match this answer to the question. – JaMiT Sep 03 '20 at 00:52
  • @JaMiT interesting, that's what I get for not looking at the *whole* edit history. Unfortunately I don't have a lot of experience with using `>>` to read strings, so I don't have any confidence in editing my answer to be accurate with this new information. – Mark Ransom Sep 03 '20 at 02:46