Scanf for not the same amount of data in C - arrays

I am trying write a code for program in C, but i found a problem i am not able to solve. I get a set of input, but the input is not always the same. How do i use scanf to read not always the same amount of data?
Input 1):
+ 12345 Lala
Input 2):
- 12345
If i use something like this:
scanf("%s %d %s", a[i], &b[i], c[i]);
the terminal requests more data for me (which i understand). So how do i use scanf to sometimes read all three (string, integer, string) and sometimes just two (string, integer)?

Start by reading the whole line
char line[100];
scanf(" %[^\n]", line);
or
fgets(line, 100, stdin);
Then use sscanf to read the values from the line.
int itemsRead = sscanf(line, "%s %d %s", a[i], &b[i], c[i]);
The return value of sscanf will tell you how many values you successfully read from the line.

You can try fgets:
char *fgets(char *s, int size, FILE *stream);

Related

Segmentation fault in sscanf while reading FILE

When I compile my program I get no error, but when I start it I get a "Segmentation fault". The FILE I try to read is build like this:
322;Peter;m
233;Chad;m
211;Lisa;w
I have the strong feeling my sscanf function is the issue.
Please help me.
#define MAXCHAR 30
#define MAXZEILE 40
void speicher(char Z[MAXCHAR]){
FILE *QUELL;
int a;
char n[MAXCHAR];
char g;
char string[MAXZEILE];
QUELL=fopen(Z,"r");
fgets(string, MAXZEILE, QUELL);
sscanf(string, "%d;%s;%c", &a, n, &g);
printf("%d, %s, %c", a, n, g);
fclose(QUELL);
}
My bad:
the MAXCHAR for the FILE input was to low.
The FILE had more than 30 chars.
In your sscanf %s does not know when to stop:
sscanf(string, "%d;%s;%c", &a, n, &g);
Without properly tokenizing on ;, %s will keep grabbing input until the next whitespace (which in your case will be the end of the line). It should be changed to
sscanf(string, "%d;%[^;];%c", &a, n, &g);
The %[^;] specifies to grab characters that are not a ; thus achieving the desired result.
For more robustness, you may want to look into using strtok to first separate it ; and then process each individual segment.
I assume that to your purposes the lines written below are enough
ReturnVal = sscanf(strinp1, "%d %c %100[^;] %c %c", &a, &Separator1,
n,&Separator2, &g);
Read an integer
Read then the character ';'
Read at most 100 characters, stop reading encountering the character ';'
Read then again the character ;
Read the next character. (man or woman???).

Simple test program using sscanf does not work

I was wondering why the following does not work:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int nbytes = 100;
char* string;
string = malloc((sizeof(char) * nbytes) + 1);
int x, y, z;
int args_assigned = 0;
while (args_assigned != 3)
{
printf("Please enter three integers separated by whitespace\n"
scanf("%s", string);
args_assigned = sscanf(string, "%d %d %d", &x, &y, &z);
}
free(string);
printf("Thanks for %d %d %d\n", x, y, z);
return 0;
}
In the original version of this code, the programmer had used getline instead of scanf, but apparently this is no longer a valid function in C99? Please correct me if I am wrong.
Anyway, I suspect the problem is to do with my use of scanf. Is there another function I should be using to provide the string for sscanf to parse? Of course, there could be something far more fundamental that I am missing here...
You ask the user to enter three integers separated by spaces.
You try to read that information with "%s" which stops reading at the first space. This is why you run into problems. You could have found this out by printing what you get from your scanf() call.
Don't forget to check the return value from sscanf().
There is a POSIX function getline() which reads a whole line and tells you how long it is. Alternatively, there is the standard C function fgets() which can be used to read whole lines.
At a pinch, you could use scanf(" %[^\n]", string), but I really wouldn't recommend it; use getline() or fgets().
Be sure to finish this line:
printf("Please enter three integers separated by whitespace\n"
To read a line of input, use fgets().
fgets(string, nbytes + 1, stdin);

fgets and sscanf getting list value twice

I'm having trouble with sscanf and fgets where it seems to be getting the last value input and re reading it back through even though we have come to the end of the file. My code:
while (won == 0) {
char command, input[MAX_LENGTH];
fgets(input, MAX_LENGTH, stdin);
sscanf(input, " %c\n", &command);
printf('%c\n', command);
check_won();
}
Your sscanf pattern is %c %s, but you're only ever reading command. Is that intentional? You should consider checking the return value of fgets to ensure that it is still actually reading input, and the return value of sscanf to ensure that it is indeed reading two elements (and discarding the second one). If your input is not being parsed and collected correctly, and your check_won function is dependent on that input, you will see repeated input because your array will not be being re-initialized.
Try something like this instead?
if(fgets(input, MAX_LENGTH, stdin) == NULL) {
break;
}
In the format string you have specified 2 elements but you have passed only one argument &command.
sscanf(input, " %c %s\n", &command);
What's happening is even though fgets fails at the EOF, your sscanf is reading the last value of input fetched by fgets. So do not do sscanf if fgets fails.
Try this
char command, input[MAX_LENGTH];
while ( won == 0 && fgets(input, MAX_LENGTH, stdin) ) {
sscanf(input, " %c\n", &command);
printf('%c\n', command);
check_won();
}

Input a special string during runtime in C

In my C code I am given the following string as input:
"c:\tc\bin\a c j k.jpg"
I tried to read the input with scanf but it failed (passing the input both with and without quotation marks) and I am looking for an other solution.
My code is as follows:
char keytext[16],zzz,source[100],dest[100];
short int a;
size_t readcount;
clrscr();
printf("input the key text(max 16 characters):");
scanf("%s",&keytext);
printf("input file name:");
scanf("%s",&source);
/*fgets(source,100,stdin);
namelen=strlen(source);
if(source[namelen-1]=='\n')
source[namelen-1]='\0';*/
printf("output file name:");
scanf("%s",&dest);
The format specifier %s will stop consuming input when the first whitespace character is encountered, so it will only read until the end of C:\tc\bin\a. To read up to the k.jpg you can use a scanset:
char input[128];
if (1 == scanf("%127[^\n]", input))
{
}
The format specifier "%127[^\n]" means read up to the next newline character but no more than 127 characters to prevent buffer overrun. You should check the return value of scanf() before using its output, it returns the number of assignments made.
scanf function with %s specificator expects pointer to char char *. But you pass the pointer to pointer to char char **.
In order to fix it use the following code instead:
scanf("%s", keytext);
scanf("%s", source);
scanf("%s", dest);
Note, it doesn't require & symbol.
If you want to read whole string with spaces, you can use fgets function.
fgets(keytext, sizeof(keytext), stdin);
fgets(source, sizeof(source), stdin);
fgets(dest, sizeof(dest), stdin);

fscanf reading newline character

I have been slowly tracking down my error for my program. I have narrowed it down to this.
I have a user input
fscanf(stdin, "%c %c %d", &car, &dir, &amount);
the first time I access it it works fine, correctly reading in the values. The second time in the loop it reads a \n into car instead of the char I give it. it then reads what should have been in car into dir. amount reads correctly. As car is passed to other functions for counting I eventually end up with a segfault.
Is it reading in the \n from the previous line or something?
The "%c" conversion specifier does not do the usual whitespace trimming.
Try adding a space before the first conversion specifier
if (fscanf(stdin, " %c %c %d", &var, &dir, &amount) != 3) { /* error */ }
Or, maybe better, read a full line and parse it within your program
char buf[1000];
fgets(buf, sizeof buf, stdin);
parse(buf);

Resources