Reputation: 3
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int a = 0, f = 0;
char ch[1];
char arr[1000];
while (f < 3) {
while (((*ch = getchar()) != 10))
{
scanf("%9s", &(arr[a]));
scanf("%9s", &(arr[a + 1]));
a += 2;
}
f++;
}
for (int i = 0; i < a; i++) {
printf("%s\n", &arr[i]);
}
return 0;
}
This code is supposed to collect input like:
1 4 green 4 green 1 blue 2 blue 4 blue 5 blue 7 blue 5 red 7 red 1 violet 2 violet 4 violet 5 violet 7 violet
1
2 4 green 4 green 7 blue 1 red 2 red 4 red 5 red 7 red 1 violet 2 violet 4 violet 5 violet 7 violet
2
3 4 green 4 green 1 blue 2 blue 4 blue 7 blue 1 red 2 red 4 red 5 red 7 red 5 violet 7 violet
3
First, there is some number, then one number and one word. I don't know how many times will there be but I know the number of input lines. The problem I encountered is when there is a space at the end of input line right before pressing 'enter' in console, program keeps on waiting for more input. I have no idea how to get rid of this especially at the last line of input because putting space at the end of last input line causes program to wait forever for a user to type something.
Upvotes: 0
Views: 194
Reputation: 164669
Let's unpack your code.
You're using getchar
to look for an end of line, but it will swallow that character. scanf
cannot see it. If you input "0123456789" getchar
will eat the 0. You could use putchar
to put it back, but it's all unnecessary.
scanf("%9s", &(arr[a]));
scanf("%9s", &(arr[a + 1]));
This is reading up to nine characters from input and sticking it into the string arr
. Then it's reading another nine characters from input and overwriting eight of the characters it just read.
To walk through it, let's say the line is "0123456789abcdefghijklmno"
getchar()
reads 0 from stdin.
scanf("%9s", &(arr[a]))
reads 123456789 from stdin and puts it in arr
starting at a
which is 0.
scanf("%9s", &(arr[a + 1]))
reads abcdefghi from stdin and puts it in arr
starting at a + 1
which is 1 overwriting all but the first character of what was just written to arr
.
arr[a]
will be "1abcdefghi".
char arr[1000]
allocates space for a single string of 999 characters (plus a null byte) to the stack. I think you mean arr
to be an array of 1000 strings, each able to hold at least 9 characters plus the null byte. That's char arr[1000][10]
.
scanf
has many problems, as does trying to read line-by-line with getchar
. Instead, it's usually better to read a line with fgets
into a buffer and parse the line with sscanf
or other string parsing functions. This avoids many issues with hanging waiting for input or unknown line size.
In this case, use strtok
(STRing TOKenizer) to split the line on whitespace. strtok
behaves a little oddly because it has its own internal buffer. It also does not allocate new memory, it returns pointers within the original line. The spaces are replaced with null bytes so it seems like you're getting just one token at a time. Use strdup
to copy the word into your array.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
// A single line buffer to reuse.
// BUFSIZ is the size of the input buffer and a good size to choose.
char line[BUFSIZ];
// An array for 1000 strings.
// No memory is allocated for the strings themselves.
// We'll allocate as needed.
//
// Note: a real problem would not allocate a fixed size array.
// It would extend `words` as needed.
// You'll learn how to do that that later.
char *words[1000];
// Track how many words are in the words array.
int num_words = 0;
// Read at most 3 lines
for(int i = 0; i < 3; i++) {
// Read a line. Exit the loop early if there's no more lines.
if( !fgets(line, sizeof(line), stdin) ) {
break;
}
// Split the line on whitespace.
// fgets() does not strip newlines.
// We must include newline else it will be considered a word.
for(
char *word = strtok(line, " \t\n");
word;
word = strtok(NULL, " \t\n")
) {
// word is a pointer to memory inside line.
// The whitespace has been replaced by a null byte so we can
// read a single word. We could store that and save memory,
// but `line` will be reused to read the next line and
// the previous words will be overwritten.
// So we need to copy the word. `strdup` allocates just the
// right amount of memory.
words[num_words] = strdup(word);
num_words++;
}
}
for (int i = 0; i < num_words; i++) {
printf("%s\n", words[i]);
}
return 0;
}
You should be able to adapt that basic code to read lines of words to your specific task.
Upvotes: 1