Read in digits until a newline character is hit - c

I have a text file that looks like the following:
12345678909876543211234567890
09876543122345678900
I will eventually need to add these two values together using separate stacks so I want to push each digit into a stack separately so I have code like the following:
test=fopen("test.txt","r");
while (!feof(fp)) {
fscanf(test, "%1d", &number);
Push((Item)number, &num1);
}
I need to modify my code though so that it reads the first line 1 digit at a time, pushing on each digit, and then for the next line I need it to push into another stack called num2 instead of num1 as you see in the current code.

You've not told us about the stack types, so I'm inventing one — typedef name is Stack:
Stack num1, num2;
Stack *stacks[2] = { &num1, &num2 };
…initialize stacks
…open file and check that the open was successful
for (int i = 0; i < 2; i++)
{
char line[4096];
if (fgets(line, sizeof(line), test) == 0)
…report unexpected EOF or other error; do not continue…
char *digit = line;
while (isdigit((unsigned char)*digit))
Push((Item)(*digit++ - '0'), stacks[i]);
if (*digit != '\n' && *digit != '\0')
…report unexpected (non-digit) data on input; do not continue;
}
I assume that Push is a function, not a macro that might evaluate its first argument more than once. If it is such a macro, the loop body needs be split onto two lines and braces added so that the increment of digit is separate from the function call.
Note that one major advantage of this method is that you have the whole line of data available for error reporting, which is typically easier for people to understand than only being able to report on the dribs and drabs left over after a semi-indeterminate number of characters was read from the line by a scanf() loop. You can even use sscanf() on the line if you want to — see How to use sscanf() in loops?

Related

Store hex input into int variable without using scanf() function in C

Pre-History:
I had the issue, that the getchar() function did not get processed in the right way as there was not a request for any given input and the program just have continued processing further.
I searched the internet about what this issue could be and found the information that if the scanf() function is implemented into a program before the getchar() function, the getchar() function does not behave in the right way, and would act like my issue was.
Citation:
I will bet you ONE HUNDRED DOLLARS you only see this problem when the call to getchar() is preceded by a scanf().
Don't use scanf for interactive programs. There are two main reasons for this:
1) scanf can't recover from malformed input. You have to get the format string right, every time, or else it just throws away whatever input it couldn't match and returns a value indicating failure. This might be fine if you're parsing a fixed-format file when poor formatting is unrecoverable anyway, but it's the exact opposite of what you want to do with user input. Use fgets() and sscanf(), fgets() and strtok(), or write your own user input routines using getchar() and putchar().
1.5) Even properly used, scanf inevitably discards input (whitespace) that can sometimes be important.
2) scanf has a nasty habit of leaving newlines in the input stream. This is fine if you never use anything but scanf, since scanf will usually skip over any whitespace characters in its eagerness to find whatever it's expecting next. But if you mix scanf with fgets/getchar, it quickly becomes a total mess trying to figure out what might or might not be left hanging out in the input stream. Especially if you do any looping -- it's quite common for the input stream to be different on the first iteration, which results in a potentially weird bug and even weirder attempts to fix it.
tl;dr -- scanf is for formatted input. User input is not formatted. //
Here is the link, to that thread: https://bbs.archlinux.org/viewtopic.php?id=161294
scanf() with:
scanf("%x",integer_variable);
seems for me as a newbie to the scene as the only way possible to input a hex number from the keyboard (or better said the stdin file) and store it to a int variable.
Is there a different way to input a hex value from the stdin and store it into an integer variable?
Bonus challenge: It would be nice also, if i could write negative values (through negative hex input of course) into an signed int variable.
INFO: I have read many threads for C here on Stackoverflow about similar problems but none of those answer my explicit question quite well. So i´ve posted this question.
I work under Linux Ubuntu.
The quote about the hundred dollar bet is accurate. Mixing scanf with getchar is almost always a bad idea; it almost always leads to trouble. It's not that they can't be used together, though. It's possible to use them together -- but usually, it's just way too difficult. There are too many fussy little details and "gotcha!"s to keep track of. It's more trouble than it's worth.
At first you had said
scanf() with ... %d ... seems for me as a newbie to the scene as the only way possible to input a hex number from the keyboard
There was some side confusion there, because of course %d is for decimal input. But since I'd written this answer by the time you corrected that, let's proceed with decimal for the moment.
(Also for the moment I'm leaving out error checking -- that is, these code fragments don't check for or do anything graceful if the user doesn't type the requested number.) Anyway, here are several ways of reading an integer:
scanf("%d", &integer_variable);
You're right, this is the (superficially) easiest way.
char buf[100];
fgets(buf, sizeof(buf), stdin);
integer_variable = atoi(buf);
This is, I think, the easiest way that doesn't use scanf. But most people these days frown on using atoi, because it doesn't do much useful error checking.
char buf[100];
fgets(buf, sizeof(buf), stdin);
integer_variable = strtol(buf, NULL, 10);
This is almost the same as before, but avoids atoi in favor of the preferred strtol.
char buf[100];
fgets(buf, sizeof(buf), stdin);
sscanf(buf, "%d", &integer_variable);
This reads a line and then uses sscanf to parse it, another popular and general technique.
All of these will work; all of these will handle negative numbers. It's important to think about error conditions, though -- I'll have more to say about that later.
If you want to input hexadecimal numbers, the techniques are similar:
scanf("%x", &integer_variable);
char buf[100];
fgets(buf, sizeof(buf), stdin);
integer_variable = strtol(buf, NULL, 16);
char buf[100];
fgets(buf, sizeof(buf), stdin);
sscanf(buf, "%x", &integer_variable);
These should all work, too. I wouldn't necessarily expect them to handle "negative hexadecimal", though, because that's an unusual requirement. Most of the time, hexadecimal notation is used for unsigned integers. (In fact, strictly speaking, %x with scanf and sscanf must be used with an integer_variable that has been declared as unsigned int, not plain int.)
Sometimes it's useful or necessary to do this sort of thing "by hand". Here's a code fragment that reads exactly two hexadecimal digits. I'll start out with the version using getchar:
int c1 = getchar();
if(c1 != EOF && isascii(c1) && isxdigit(c1)) {
int c2 = getchar();
if(c2 != EOF && isascii(c2) && isxdigit(c2)) {
if(isdigit(c1)) integer_variable = c1 - '0';
else if(isupper(c1)) integer_variable = 10 + c1 - 'A';
else if(islower(c1)) integer_variable = 10 + c1 - 'a';
integer_variable = integer_variable * 16;
if(isdigit(c2)) integer_variable += c2 - '0';
else if(isupper(c2)) integer_variable += 10 + c2 - 'A';
else if(islower(c2)) integer_variable += 10 + c1 - 'a';
}
}
As you can see, it's a bit of a jawbreaker. Me, although I almost never use members of the scanf family, this is one place where I sometimes do, precisely because doing it "by hand" is so much work. You can simplify it considerably by using an auxiliary function or macro to do the digit conversion:
int c1 = getchar();
if(c1 != EOF && isascii(c1) && isxdigit(c1)) {
int c2 = getchar();
if(c2 != EOF && isascii(c2) && isxdigit(c2)) {
integer_variable = Xctod(c1);
integer_variable = integer_variable * 16;
integer_variable += Xctod(c2);
}
}
Or you could collapse those inner expressions down to just
integer_variable = 16 * Xctod(c1) + Xctod(c2);
These work in terms of an auxiliary function:
int Xctod(int c)
{
if(!isascii(c)) return 0;
else if(isdigit(c)) return c - '0';
else if(isupper(c)) return 10 + c - 'A';
else if(islower(c)) return 10 + c - 'a';
else return 0;
}
Or perhaps a macro (though this is definitely an old-school sort of thing):
#define Xctod(c) (isdigit(c) ? (c) - '0' : (c) - (isupper(c) ? 'A' : 'a') + 10)
Often I'm parsing hexadecimal digits like this not from stdin using getchar(), but from a string. Often I'm using a character pointer (char *p) to step through the string, meaning that I end up with code more like this:
char c1 = *p++;
if(isascii(c1) && isxdigit(c1)) {
char c2 = *p++;
if(isascii(c2) && isxdigit(c2))
integer_variable = 16 * Xctod(c1) + Xctod(c2);
}
It's tempting to omit the temporary variables and the error checking and boil this down still further:
integer_variable = 16 * Xctod(*p++) + Xctod(*p++);
But don't do this! Besides the lack of error checking, this expression is probably undefined, and it definitely won't always do what you want, because there's no longer any guarantee abut what order you read the characters in. If you know p points at the first of two hex digits, you don't want to collapse it any further than
integer_variable = Xctod(*p++);
integer_variable = 16 * integer_variable + Xctod(*p++);
and even then, this will work only with the function version of Xctod, not the macro, since the macro evaluates its argument multiple times.
Finally, let's talk abut error handling. There are quite a few possibilities to worry about:
The user hits Return without typing anything.
The user types whitespace before or after the number.
The user types extra garbage after the number.
The user types non-numeric input instead of a number.
The code hits end-of-file; there are no characters to read at all.
And then how you handle these depends on what input techniques you're using. Here are the basic rules:
A. If you're calling scanf, fscanf, or sscanf, always check the return value. If it's not 1 (or, in the case where you had multiple % specifiers, it's not the number of values you expected to read), it means something went wrong. This will generally catch problems 4 and 5, and will handle case 2 gracefully. But it will often quietly ignore problems 1 and 3. (In particular, scanf and fscanf treat an extra \n just like leading whitespace.)
B. If you're calling fgets, again, always check the return value. You'll get NULL on EOF (problem 5). Handling the other problems depends on what you do with the line you read.
C. If you're calling atoi, it will deal gracefully with problem 2, but it will ignore problem 3, and it will quietly turn problem 4 into the number 0 (which is why atoi is usually not recommended any more).
D. If you're calling strtol or any of the other "strto" functions, they will deal gracefully with problem 2, and if you let them give you back an "end pointer", you can check for and deal with problems 3 and 4. (Note that I left the end-pointer handling out of my two strtol examples above.)
E. Finally, if you're doing something down-and-dirty like my "hardway" two-digit hex converter, you generally have to take care of all these problems, explicitly, yourself. If you want to skip leading whitespace you have to do so (the isspace function from <ctype.h> can help), and if there might be unexpected non-digit characters, you have to check for those, too. (That's what the calls to isascii and isxdigit are doing in my "hardway" two-digit hex converter.)
Per scanf man page, you can use scanf to read hex number from stdin into (unsigned) integer variable.
unsigned int v ;
if ( scanf("%x", &v) == 1 ) {
// do something with v.
}
As per man page, %x is always unsigned. If you want to support negative values, you will have to add explicit logic.
As mentioned in the link you posted, using fgets and sscanf is the best way to handle this. fgets will read a full line of text and sscanf will parse the line.
For example
char line[100];
fgets(line, sizeof(line), stdin);
int x;
int rval = sscanf(line, "%x", &x);
if (rval == 1) {
printf("read value %x\n", x);
} else {
printf("please enter a hexadecimal integer\n");
}
Since you're only reading in a single integer, you could also use strtol instead of sscanf. This also has the advantage of detecting if any additional characters were entered:
char *ptr;
errno = 0;
long x = strtol(line, &ptr, 16);
if (errno) {
perror("parsing failed");
} else if (*ptr != '\n' && *ptr != 0) {
printf("extra characters entered: %s\n", ptr);
} else {
printf("read value %lx\n", x);
}

How can I regulate input data from user?

I'd like some assistance with understand how inputting data in a program of C works. So far I'm used the java syntax having the convenient try{}catch(){}; clause but I don't see it anywhere on C (or I haven't found it?).
Assuming I have the following array;
float f_array[10];
Normally for me to input data I'd either use a scanf(...); or a file which I can read input from, but for the shake of simplicity let's assume I use scanf(...);
And I have the following;
int i;
for(i = 0; i<10; i++){
scanf("%f", &f_array[i]);
}
Now , my question is how to restrain the user from putting in the input a character or a string or the wrong data type for that matter? Also , should I always try to initialize the array before actually putting values in it?
Note that scanf() returns number of elements successfully read, you can check it:
int success = scanf(...);
if (!success) {
scanf("%*[^\n]%*c"):
// OR while(getchar() != '\n');
}
There is, however, a complex solution. You don't use scanf(), but write a custom input method that processes keystrokes and filters out invalid characters, possibly using getch() (Windows/nCurses). Here's a minimized Windows version:
void readFloat(float* in){
int ch, ind = 0;
char buf[100];
while (1){
ch = getch();
if (ch >= '0' && ch <= '9' || ch == '.') {
buf[ind++] = (char)ch;
putchar(ch);
}
else if (ch == 8) /* Backspace */ {
printf("\b \b");
ind --;
}
}
buf[ind] = '\0';
float ret;
sscanf(buf, "%f", &ret);
return ret;
}
So a possible result of the code:
User input (key presses): 123aaa.bbb456
Program filter (displayed on screen): 123.456
Return value: (float)123.456
Now , my question is how to restrain the user from putting in the input a character or a string or the wrong data type for that matter?
Without dedicated hardware support (say, using a keyboard that does not have letter keys, or some device that gives the user an electric shock to discourage them from hitting the 'A' key) there is no way to restrain a user from entering unwanted data.
Instead, you need to write your code with the ASSUMPTION that the user will enter invalid or poorly formed data, and cope with that. It is true that your code is simpler if you can assume an obedient and tractable user who only gives correct input, but the real world isn't like that.
scanf() - reading and interpreting data directly from stdin doesn't actually work well with such an assumption. The return value from scanf() can give you an indication a problem after the fact (e.g. the return value is number of fields successfully input, or EOF). However, when a problem occurs, scanf() handles it in a way you cannot control. Let's say you code has a
scanf("%f", &f_array[i]);
and the user hits the 'X' followed by the Enter key. scanf() will recognise the 'X' character is waiting to be read, and return immediately. The value it returns will not be 1 (which would indicate success). Even worse, the 'X' will be left to be read by a subsequent call of scanf() and the same will happen again (unless a different format is specified). Which means, if you call scanf() in a loop this way, the same will happen over and over again.
Some folks will tell you to simply find a way to read and discard the character 'X'. The problem with that approach is that there are MANY ways for the user to enter bad inputs, and you need to account for all of them. If the user does something you (or your code) doesn't expect, you get problems (e.g. program hanging waiting for the same input repeatedly, input being used as data when it isn't). You're back where you started.
The more robust approach is to simply read a line of input, and do checks before trying to extract a floating point value from it, such as
char buffer[20];
int got_one = 0;
while (!gotone && fgets(buffer, sizeof buffer, stdin) != NULL)
{
if (check_string(buffer))
{
if (sscanf(buffer, "%f", &f_array[i]) == 1)
{
/* yay - we got a floating point value */
got_one = 1;
}
else
{
fprintf(stderr, "Floating point scanning failed. Try again\n");
}
}
else
{
fprintf(stderr, "Bad data discarded. Try again\n");
}
}
Essentially, this provides several hooks so you can check user input in various ways. If you want to, it can be adapted to discard part of a line, and scan useful data from whatever's left.
The key, however, is that the code does not assume the user is well behaved. It only attempts to read a floating point value after a gauntlet of checks, and still copes if the reading fails.
The code can also be adapted to deal with users who enter data that overflows the buffer (e.g. entering 30 floating point characters on a single line). I'll leave that as an exercise.
Also , should I always try to initialize the array before actually putting values in it?
That depends on the needs of your code, but generally speaking I would not bother.
With approaches like I suggest above, you can avoid a circumstance of using the array (or elements of the array) unless valid data has actually been put into it.
All initialising the array will do is obscure cases where the code doing input (reading from the user) has not properly dealt with bad user input.
give the user some feedback on a per input basis.
process each input and allow user to make corrections as you go.
use "atof()" to do the conversion, but it has a couple of quirks:
it tells you there is an error by returning a value of 0.0
it stops processing if/when it finds an invalid char and returns what it has up to that point
eg. 6.35k gives 6.35 -- this usually works out ok;
otherwise you have to check for invalid chars yourself.
try this
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main () {
float f_array[10];
int i;
float input_value;
char temp_string[32];
for(i = 0; i<10; i++){
printf("input a floating point number: ");
scanf("%s",&temp_string[0]);
input_value = atof(temp_string);
while(input_value == 0.0) {
printf("%s is not a valid floating point number\n");
printf("example is 5.6 or 1e32 or 17\n");
printf("try again - input a floating point number: ");
scanf("%s",&temp_string[0]);
input_value = atof(temp_string);
}
f_array[i] = input_value;
printf("String value = %s, Float value = %f\n", temp_string, input_value);
}
/* use the data */
for(i = 0; i<10; i++){
printf("%f\n",f_array[i]);
/* do something */
}
}

fscanf() how to go in the next line?

So I have a wall of text in a file and I need to recognize some words that are between the $ sign and call them as numbers then print the modified text in another file along with what the numbers correspond to.
Also lines are not defined and columns should be max 80 characters.
Ex:
I $like$ cats.
I [1] cats.
[1] --> like
That's what I did:
#include <stdio.h>
#include <stdlib.h>
#define N 80
#define MAX 9999
int main()
{
FILE *fp;
int i=0,count=0;
char matr[MAX][N];
if((fp = fopen("text.txt","r")) == NULL){
printf("Error.");
exit(EXIT_FAILURE);
}
while((fscanf(fp,"%s",matr[i])) != EOF){
printf("%s ",matr[i]);
if(matr[i] == '\0')
printf("\n");
//I was thinking maybe to find two $ but Idk how to replace the entire word
/*
if(matr[i] == '$')
count++;
if(count == 2){
...code...
}
*/
i++;
}
fclose(fp);
return 0;
}
My problem is that fscanf doesn't recognize '\0' so it doesn't go in the next line when I print the array..also I don't know how to replace $word$ with a number.
Not only will fscanf("%s") read one whitespace-delimited string at a time, it will also eat all whitespace between those strings, including line terminators. If you want to reproduce the input whitespace in the output, as your example suggests you do, then you need a different approach.
Also lines are not defined and columns should be max 80 characters.
I take that to mean the number of lines is not known in advance, and that it is acceptable to assume that no line will contain more than 80 characters (not counting any line terminator).
When you say
My problem is that fscanf doesn't recognize '\0' so it doesn't go in the next line when I print the array
I suppose you're talking about this code:
char matr[MAX][N];
/* ... */
if(matr[i] == '\0')
Given that declaration for matr, the given condition will always evaluate to false, regardless of any other consideration. fscanf() does not factor in at all. The type of matr[i] is char[N], an array of N elements of type char. That evaluates to a pointer to the first element of the array, which pointer will never be NULL. It looks like you're trying to determine when to write a newline, but nothing remotely resembling this approach can do that.
I suggest you start by taking #Barmar's advice to read line-by-line via fgets(). That might look like so:
char line[N+2]; /* N + 2 leaves space for both newline and string terminator */
if (fgets(line, sizeof(line), fp) != NULL) {
/* one line read; handle it ... */
} else {
/* handle end-of-file or I/O error */
}
Then for each line you read, parse out the "$word$" tokens by whatever means you like, and output the needed results (everything but the $-delimited tokens verbatim; the bracket substitution number for each token). Of course, you'll need to memorialize the substitution tokens for later output. Remember to make copies of those, as the buffer will be overwritten on each read (if done as I suggest above).
fscanf() does recognize '\0', under select circumstances, but that is not the issue here.
Code needs to detect '\n'. fscanf(fp,"%s"... will not do that. The first thing "%s" directs is to consume (and not save) any leading white-space including '\n'. Read a line of text with fgets().
Simple read 1 line at a time. Then march down the buffer looking for words.
Following uses "%n" to track how far in the buffer scanning stopped.
// more room for \n \0
#define BUF_SIZE (N + 1 + 1)
char buffer[BUF_SIZE];
while (fgets(buffer, sizeof buffer, stdin) != NULL) {
char *p = buffer;
char word[sizeof buffer];
int n;
while (sscanf(p, "%s%n", word, &n) == 1) {
// do something with word
if (strcmp(word, "$zero$") == 0) fputs("0", stdout);
else if (strcmp(word, "$one$") == 0) fputs("1", stdout);
else fputs(word, stdout);
fputc(' ', stdout);
p += n;
}
fputc('\n', stdout);
}
Use fread() to read the file contents to a char[] buffer. Then iterate through this buffer and whenever you find a $ you perform a strncmp to detect with which value to replace it (keep in mind, that there is a 2nd $ at the end of the word). To replace $word$ with a number you need to either shrink or extend the buffer at the position of the word - this depends on the string size of the number in ascii format (look solutions up on google, normally you should be able to use memmove). Then you can write the number to the cave, that arose from extending the buffer (just overwrite the $word$ aswell).
Then write the buffer to the file, overwriting all its previous contents.

How to get 3 chars entered with spaces in scanf into a char array?

I am previously a java programmer, but I'm now doing a C course at university (computer science major).
I need the user to be able to enter 3 chars,the first 2 being numbers, and the last 1 being either 'v' or 'h'.
For example "1 2 v".
I need the user to be able to enter it with the spaces in between each character.
This is my current code:
void manageInput(char box[][width]){
char move[4];
char input[16];
while(1){
scanf("%s", input);
int i = 0;
while(input[i] != 0){
if(input[i] != ' ' && input[i] != "\n"){
move[i] = input[i];
}
i++;
}
printf("%s\n", move);
makeMove(box, move);
printBox(box, height, width);
// TODO
if(move[0] == 'x'){
exit(0);
}
}
}
However if I run it, it works fine when I enter the chars with out spaces like "12v", but If I enter "1 2 v", it will print out "1", call printBox, then print out "2", then print out box again, and so on.
If someone could explain what I'm doing wrong here, I would appreciate it.
If someone could explain what I'm doing wrong here, I would appreciate it.
The short story is: Your code doesn't fulfill your requirements. It simply doesn't do what you want it to do.
Your requirements are:
All fields must be one character. This requirement isn't fulfilled by your code. Your code will mistakenly accept multiple characters per field.
There must be one space (exactly one space?) between the fields. This requirement isn't fulfilled by your code. There might be multiple spaces between the fields, and your code will mistakenly accept that.
In fact, your code invokes undefined behaviour by accessing the move array out of bounds. Consider that as a consequence of one of the above scenarios i might become some value higher than 3. What might happen in this code: move[i] = input[i];?
Your code is also way too complex. All of your functionality can be performed by scanf alone. It's a very powerful function, when you know how to use it correctly... I suggest reading and understanding the manual multiple times, when you have an opportunity. You'll learn a lot!
I notice something you neglected to mention from within the logic you have presented: It's expected that the first field might also be 'x', which corresponds to an exit usecase. This is a bad design; the caller has no opportunity to clean up... but I'll run with it. You really should use return (and return an int value or something, corresponding to error/success) instead.
Let us caste that last paragraph aside, because we can simply consider 'x' to be invalid input (and exit as a result), and I don't want to change the contracts of your functions; I'll leave that to you. The expression described so far appears to be int x = scanf("%1[0123456789]%*1[ ]%1[0123456789]%*1[ ]%1[vh]", a, b, c);.
Note that it is expected that a, b and c will have enough space to store a string of one byte in length. That is, their declaration should look like: char a[2], b[2], c[2];.
Make sure you check the return value (x, in the example)! If x is 3, it's safe to assume that the three variables a, b and c are safe to use. If x is 2, it's safe to assume that a and b are safe to use, and so on... If x is EOF or 0, none of them are safe to use.
By checking the return value, you can reject input that doesn't match that precise pattern, that is:
Fields that aren't exactly one byte in width will be rejected.
Too many or too few spaces will be rejected.
Something else popped up that you have neglected to mention, and it's also present within your code: Chux mentioned that you'll likely be expecting the input to be terminated with a '\n' (newline) character. This can also be implemented in a number of ways using scanf:
scanf("%1*[\n]"); will attempt to read and discard precisely one '\n' character, but there's no way to ensure that was successful. getchar would be more appropriate for that purpose; something along the lines of if (getchar() != '\n') { exit(EXIT_FAILURE); } might make sense, if you wish to ensure that the lines of input are perfectly formed and bomb out when they aren't... #define BOMB_OUT?
scanf("%*[^\n]"); scanf("%*c"); makes more sense; If you're interested in reading one item per line, then it makes sense to discard everything remaining on the line, and then the newline character itself. Note that your program should always tell the user when it's discarding or truncating input. You could also use getchar for this.
void manageInput(char box[][width]){
for (;;) {
char a[2], b[2], c[2];
int x = scanf("%1[0123456789]%*1[ ]%1[0123456789]%*1[ ]%1[vh]", a, b, c);
if (x != 3) {
/* INVALID INPUT should cause an error value to be returned!
* However, this function has no return value (which makes it
* poorly designed)... Calling `exit` gives no opportunity for
* calling code to clean up :(
*/
exit(EXIT_FAILURE);
}
if (getchar() != '\n') {
# ifdef BOMB_OUT
exit(EXIT_FAILURE);
# else
scanf("%*[^\n]");
getchar();
puts("NOTE: Excess input has been discarded.");
# endif
}
char move[4] = { a[0], b[0], c[0] };
printf("%s\n", move);
makeMove(box, move);
printBox(box, height, width);
// TODO
if(move[0] == 'x'){
exit(0);
}
}
}
%s reads a whitespace-delimited string with scanf, so if that's not what you want, it's not the thing to use. %c reads a single character, but does not skip whitespce, so you probably also want a (space) in your format to skip whitespace:
char input[3];
scanf(" %c %c %c", intput, input+1, input+2);
will read 3 non-whitespace characters and skip any whitespace before or between them. You should also check the return value of scanf to make sure that it is 3 -- if not, there was less than 3 characters in your input before an end-of-file was reached.
It's usuall a bad idea to read string via scanf because of potential buffer overflow. Consider using fscanf or better fgets as in
fgets(input, 15, stdin);
Note the extra byte for '\0'.
Also, you're comparing char to string here: input[i] != "\n". It should be input[i] != '\n' instead.
And btw you can just use something like
int x, y;
char d;
scanf("%d%d%c", &x, &y, &d);
This looks like two simple bugs.
You need to use separate indexes for move[] and input[]
int i = 0;
while(input[i] != 0){
if(input[i] != ' ' && input[i] != "\n"){
move[i] = input[i];
}
i++;
}
Imagine input of 1 2 v
input[0] != 0, so we enter the loop
it's not ' ' or '\n' either, so we copy input[0] to move[0]
so far so good
You increment i, and discover that input[1] == ' '
But then you increment i again
You discover that you are interested in input[2] (2) - so you copy it to move[2], rather than move[1]. Oops!
Then to make things worse, you never put an end-of-string character after the last valid character of move[].

Reading Stdin in chunks... (possibly with scanf?)

I have a linux box.
On this linux box, there is a program.
In this program, I have a loop like this:
int num=*"what num needs to be"*;
char proc[num];
int result;
while (1) {
result=scanf("%[^'&']%s",proc);
printf("And proc is: %s\n",proc);
printf("Result counter was: %i\n",result)
if (result == 0) break;
}
scanf("%[^'&'],%s",proc)
printf("post lop result is: %s", proc);
As you may have guessed, stdin contains data I need delineated by the '&' character.
As I'm hoping someone more skilled than me has guessed, the output looks something like:
And proc is: *first delineated section*
Result counter was: 1
And proc is: *first delineated section*
Result counter was: 0
post loop result is: *first delineated section*
I thought that scanf was supposed to consume the part of stdin it has already read. Why isn't it doing this?
Also, FYI: this is being run on a very cheap, slow server. Volume may or may not become more than slight. Efficiency is thus a plus, I'm open to however someone might suggest I do this....
Thanks!
The scanset does not need two single quotes in it — one is sufficient if you want to break on a single quote, but I suspect you only want to stop on &, and the code below assumes that too. Once you've read up to the first &, you need some code to read the &. You need to check the result of scanf() before using the data it returned.
Hence:
int num = 100;
char proc[num];
int result;
while ((result = scanf("%99[^&]", proc)) == 1)
{
printf("And proc is: <<%s>>\n", proc);
printf("Result counter was: %i\n", result);
int c;
while ((c = getchar()) != EOF && c != '&')
;
}
You also need to decide whether newlines mark the end of a field too...if they do, then:
int num = 100;
char proc[num];
int result;
while ((result = scanf("%99[^&\n]", proc)) == 1)
{
printf("And proc is: <<%s>>\n", proc);
printf("Result counter was: %i\n", result);
int c;
while ((c = getchar()) != EOF)
{
if (c != '&' && c != '\n')
{
ungetc(c, stdin);
break;
}
}
}
Note the use of %99[...] to prevent buffer overflows. The angle brackets <<%s>> simply mark the start and end of the string; they make trailing blanks and tabs visible, for example.
The code assumes you have a C99 compiler that allows variable declarations midway through a block of code. If not, move int c; to the top of the loop
The problem is that on the second iteration the scanf can't read the format you gave it (the line read from standard input does not match) and doesn't modify proc. That's also the reason it returns 0: it has successfully read (and thus modified) 0 fields.

Resources