1

I'm doing some basic input parsing in c/c++.

format: number of values, followed by space separated values:

3
5 2 4

The problem here is the lack of a space after the first line. This causes cin and scanf to read 35 into the first variable, instead of 3.

int num;

scanf("%d", &num);

int array[num];
for (int i = 1; i <= num; i++) {
    scanf("%d", &array[i]);
}

How do I get cin, or scanf, to stop parsing at a newline?

Edit: Is it bad not to init variables even if they are written to later, before being read? (int num)

It works if I type the input in, but not if I paste it. Any clue?

Filip Haglund
  • 13,919
  • 13
  • 64
  • 113
  • 1
    They both stop at the first whitespace. A new line is a white space, so they both stop there. – James Kanze Aug 04 '13 at 21:03
  • 1
    Post a small, complete program that shows the problem. `scanf` and stream extractors do **not** ignore line ends. – Pete Becker Aug 04 '13 at 21:03
  • Are you sure the file has a newline there? Are you sure this is where the problem is? Are you aware that you're using a compiler-specific extension to the language by defining the length of an array dynamically? – Dave Aug 04 '13 at 21:05
  • Get this to work with one value before you try an array. – Beta Aug 04 '13 at 21:12
  • the first element is undefined – Dave Aug 04 '13 at 21:13
  • 2
    The real question is, are you using C, or C++? – Cornstalks Aug 04 '13 at 21:26
  • C++, but C code should still work in C++, right? – Filip Haglund Aug 04 '13 at 21:29
  • @Cornstalks - no, that's not particularly important. The answer is the same for both languages. – Pete Becker Aug 04 '13 at 21:29
  • 3
    @FilipHaglund: Some C code should work in C++, but not all C code. The code you posted is valid C99 code, but not valid C++ code, for example. – Cornstalks Aug 04 '13 at 21:30
  • @PeteBecker: Not necessarily. If I were using C++, I'd use `vector`s and streams. Additionally, variable length arrays are not legal in C++ (without compiler extensions). If I were using C, I'd write completely different code. – Cornstalks Aug 04 '13 at 21:31
  • @PeteBecker; Yes, that's particularly important. Because VLA's are not allowed in C++. – haccks Aug 04 '13 at 21:32
  • @Cornstalks - um, the question is about the behavior of **scanf**, not about how you might have written the code differently. – Pete Becker Aug 04 '13 at 21:33
  • @haccks - the use of a VLA on a compiler that supports them does not change the behavior of `scanf`, which is what the question is about. – Pete Becker Aug 04 '13 at 21:34
  • @PeteBecker; I know, but your comment *The answer is the same for both languages* is wrong. – haccks Aug 04 '13 at 21:36
  • @PeteBecker: While the question does ask about `scanf`, the ideal answer would include the solution in *proper* C++ in addition to explanations about `scanf`. – Cornstalks Aug 04 '13 at 21:36
  • 1
    @PeteBecker The question is about `scanf` _and_ `std::cin`. The _example_ is about `scanf`. – Captain Obvlious Aug 04 '13 at 21:37
  • Sigh. God save us from language purists who can't see the forest for the trees. – Pete Becker Aug 04 '13 at 21:38
  • @CaptainObvlious - if that's your emphasis, then the assertion that I replied to, "the real question is, are you using C, or C++", is merely snarky. – Pete Becker Aug 04 '13 at 21:45

8 Answers8

4

std::cin interprets newline characters as spaces so there is the possibility the file you are working with contains something other than a newline. You are also using a non-standard extension to declare the array. This is not portable and not guaranteed to be supported by all compilers. I suggest you switch to using std::vector instead.

Your for loop is also incorrect. Array's used zero based indexing to access their elements. Because of this you end up accessing the array out of bounds which is undefined behavior. This means your program might crash, it may overwrite other variables or you might not notice any symptoms at all. This may also cause the symptom you are experiencing if it overwrites other variables.

The example below uses C++ input streams instead of scanf to provide better error checking.

#include <istream>
#include <vector>

std::vector<int> load(std::istream& in)
{
    std::size_t count;
    std::vector<int> data;

    // If the user does not enter a number "in >> count" will fail.
    if (in >> count)
    {
        int value;
        while (count-- && in >> value)
            data.push_back(value);
    }

    return data;
}


#include <iostream>

int main()
{
    auto data = load(std::cin);
    for (auto i : data)
        std::cout << i << std::endl;
}

You can test this without reading from a file by using std::stringstream as the input.

#include <iostream>
#include <sstream>
int main()
{
    std::stringstream text("3\n5 2 4");
    auto data = load(text);

    for (auto i : data)
        std::cout << i << std::endl;
}
Captain Obvlious
  • 19,754
  • 5
  • 44
  • 74
1

Within the for loop you started the array at position 1 and not 0. Which would cause going out of bounds, as you wanted to write to element 2 of the array. If you allocate an array of 2 elements the valid elements are going to be 0 and 1. This code works:

int num;

scanf("%d", &num);

int array[num];

for (int i = 0; i < num; i++)
{
    scanf( "%d", &array[i] );
}
North-Pole
  • 610
  • 4
  • 13
1
#include <stdio.h>
#include <stdlib.h>

int main()
{
    int num;
    scanf("%d", &num);

    int *array= malloc(sizeof(int) *num);    // num is known at runtime
    int i;
    for (i = 0; i < num; i++) {    //starts at 0, ends at num - 1 
        scanf("%d", &array[i]);
    }
    for (i = 0;i< num; i++) {
        printf("%d", array[i]);
    }
    free(array);
}
Prashant Kumar
  • 20,069
  • 14
  • 47
  • 63
Lidong Guo
  • 2,817
  • 2
  • 19
  • 31
1

Start array from 0 as array indexes start from 0 - like:

for (int i = 0; i < num; i++) 

You are starting first element from 1 that makes it undefined. Moreover, you should make dynamic array.

Shumail
  • 3,103
  • 4
  • 28
  • 35
1

[Edit: The Answere is specific to C++, as the Question also have a C++ tag]

Well first thing first.

You array defination is wrong .

int array[num];    // Super wrong way

You are not supposed to pass a variable as index while defining an array, its not allowed. Else, it will cause "nasal demon".

int * array = new int[num]    //correct way

The code might be working correctly now but the array definition given by you lies under the category of UB.

Prashant Kumar
  • 20,069
  • 14
  • 47
  • 63
Dr. Xperience
  • 475
  • 1
  • 5
  • 18
1

I liked Lidong Guo's code, and have modified it to run with Microsoft's C Compiler. The only change was to move all of the data definitions ahead of any executable code, plus I added a space between the printed numbers.

  #include <stdio.h>
  #include <stdlib.h>
  main()
  {
       int num;

       int *array; //[num];
       int i;

       scanf("%d\n", &num);//here deal with the newlinw
       array= malloc(sizeof(int) *num);//[num];

       for (i = 0; i < num; i++)
       {//the loop .start 0 end num -1
          scanf("%d", &array[i]);
       }

       for (i = 0; i < num; i++)
       {
          printf("%d ", array[i]);
       }

       free(array);
 }
JackCColeman
  • 3,777
  • 1
  • 15
  • 21
0

Start your loop from 0 and end it at num-1,i.e

for (int i = 0; i < num - 1; i++) 
    scanf("%d", &array[i]);   

And the reason for pasted input does not work is that it doesn't contain newline between two lines

haccks
  • 104,019
  • 25
  • 176
  • 264
0

Change the

scanf

statement to

scanf("%d", &array[i]);

Also array indexing starts from 0 and ends at num-1

nj-ath
  • 3,028
  • 2
  • 25
  • 41