Apologizes I am very inexperienced with C. I have the following code:
char * a[BUF_SIZE];
scanf("%d", numberOf);
do {
a[i] = (char *)malloc(MAX_LINE_LEN + 1);
scanf("%s", a[i]);
++i;
} while(i < numberOf);
The idea is simple, read two inputs from stdin using scanf, the first being a single int, followed by some array of strings. Scanf works independently in both cases e.g. scanf("%d", numberOf) will store a digit and scanf("%s", a[i]) will store a set of strings into the array. However in conjunction reading an integer first into numberOf causes a segfault when reading in a set of strings. My question is why? I know its generally bad practice to use scanf, but I fail to see how reading in multiple inputs from stdin can cause a segfault in the resulting code. Much Thanks!
From the code, it looks like numberOf is an int. When using scanf, you want to pass it a pointer, so change scanf("%d", numberOf); to scanf("%d", &numberOf);
What scanf does is take the user input and put it into the memory address specified by the second parameter. When you provide an int as the second parameter, scanf tries to put user input into a memory address (specified by the int) that it may not own, causing the seg-fault.
You are missing & operator in scanf("%d", numberOf); put it as &numberOf
Related
I'm in my first steps in C programming, and I came across a task I can not find a solution to.
The task is simple: taking a character from the user.
After that, you receiving a string from the user until the user types the * character.
Then print the number of times the user typed the first character.
I was able to solve the problem using char [SIZE]ת when I placed a maximum input size of 255 bytes (#define SIZE 255).
Nevertheless, my teacher tells me that although the solution is working well, this was not the purpose of the exercise, also, I can not assume a maximum string size.
He asks us to use the input buffer.
No dynamic memory allocation is used in the exercise, and only the stdio.h library is allowed.
I read a lot about the input buffer, but I still have not found the possibility to solve the exercise - how can I absorb value from the user without knowing its size?
I would be happy to receive assistance and tips on how to use the input buffer correctly.
Or more focused, how to input values (string of characters) into the input buffer, and then go over each character separately in this string and process it.
Thank You
There is no need to store all characters. Once you have read a character you can throw it away and just increase a counter. Something like this:
#include <stdio.h>
int main() {
char c, first;
int counter=0;
printf("Enter first character: ");
scanf("%c", &first);
do {
scanf("%c", &c);
if(c == first)
counter++;
} while (c != '*');
printf("You entered '%c' %d times\n", first, counter);
}
Output:
Enter first character: a
aaaaa*
5
or
Enter first character: a
aabbaa*
You entered 'a' 4 times
Note:
As been pointed out in the comments, scanf is not a good tool for this kind of stuff. I would advice against the usage of it, unless you know it is the right tool. But that's beside the point. The point here was to show you that you don't need to store the whole input buffer. If you want to look at alternate input methods (as William Pursell suggested in the comments) you could have a look at fgetc, getc, or getchar for reading single characters. fread is also a tool you should get familiar with.
Hope you guys can help me with a problem I'm having.
So I have this C code snippet:
int i = 0;
int q = 0;
scanf("%d %d", &i, &q);
When the user enters 4 5, the values 4 and 5 are stored in i and q respectively.
But when the user enters 99.99, 99 is stored in i, but the other 99 after the point goes missing. I do know how scanf works and I understand that scanf will stop scanning after ., but where does the second value go to?
Even if I do:
int i = 0;
int q = 0;
int k = 0;
scanf("%d %d", &i, &q);
scanf("%d", &k);
I still cant get the second value. Where does the second value go and how can I get store it in my variable?
It is trying to look for integer but it is not integer that is left in stdin so it fails.
You can get desired behavior if you do this
int a,b;
scanf("%d.%d",&a,&b);
printf("%d,%d",a,b);
This prints 99,99 as expected.
For your information,
scanf stops at the first mismatch and leaves the rest of the target objects untouched.
Also the unmatched data is left in the input buffer, available for a subsequent read using scanf etc.
Also you can check the return value to determine how many "items" scanf matched.
scanf() doesn't ignore the . while expects to read an int. I suggest you use fgets() and then try to parse with sscanf() which is a better approach. Something like:
#include <stdio.h>
int main(void)
{
int i = 0;
int q = 0;
char line[256];
if (fgets(line, sizeof line, stdin)) {
if (sscanf(line, "%d.%d", &i, &q) == 2) {
printf("i=%d, j=%d\n", i, q);
} else {
printf("Coudn't scan 2 ints\n");
}
} else {
printf("Couldn't read a line\n");
}
}
Note that fgets() will also read in the newline character if there's space in the buffer. It doesn't matter in this case.
But you need to be aware of it and may be undesirable in some cases (e.g., reading a name).
Also see: Why does everyone say not to use scanf? What should I use instead?
Let X be the following statement...
I do know how scanf works
Let Y be the following statement...
... but where does the second value go to?
X and Y do not correspond. Either you know about the return value of scanf, or you don't know how scanf works. That's the bottom line.
... but where does the second value go to?
According to the fscanf manual,
The fscanf() functions shall execute each directive of the format in turn. If a directive fails, as detailed below, the function shall return. Failures are described as input failures (due to the unavailability of input bytes) or matching failures (due to inappropriate input).
The space directive won't match the . input, which will cause a matching failure, scanf will return, meaning that nothing beyond the . byte will be consumed from stdin. In fact, scanf will even put the . back into stdin for you, just before it returns... Isn't that nice?
I gather you understand this (because you said "I do know how scanf works"), yet you seem to be asking about that second value which couldn't have been read due to a previous matching failure... thus, the answer to your first question is, the second value doesn't exist. It can't exist yet, because an input format error exists prior to it.
While we're on the topic of scanf, return values and matching failures, for the remaining question I'm going to assume your code actually looks something more like this:
int i = 0;
int q = 0;
if (scanf("%d %d", &i, &q) != 2) {
puts("Discarding invalid input");
scanf("%*[^\n]"); // discard up to the next newline and...
getchar(); // discard that newline, too.
// XXX: You might want to `return` or `continue` or something
}
... and how can I get store it in my variable?
As mentioned earlier, the space directive doesn't match the period. You need to replace that with something which manipulates the input stream as you intend... That's difficult for me to answer, because I don't have that information, but here's what I'd suggest: Split the two conversions up into two separate calls to scanf. This should give you a nice place in between the two calls to scanf to insert your period-handling code.
Here's a before & after, side-by-side, of the idiom I've adopted for that kind of input:
// BEFORE // AFTER
if (scanf("%d %d", &i, &q) != 2) { if (scanf("%d", &i) != 1) {
// ... puts("Invalid first input...");
// XXX: Handle this???
// XXX: `return` or `continue` or something
}
// XXX: Read a character, check if it's a space (or a dot, or something else which you have in your mind and I don't have in mine)
if (scanf("%d", &q) != 1) {
// ...
Handling the erroneous period could be as simple as exiting the process or calling getchar() to discard a single character, then continueing in order to try again. These solutions won't solve all user input errors, and might even confuse or frustrate some users. I recommend sticking with the discard the rest of the line method, at least until you learn about all of the alternatives for user input and what they're each best at. After all, people tend to avoid using software which confuses them...
... hence the reason people tend to discourage scanf... because I guess there's no such thing as literature which sets a standard, and thus there's no way to correct my scanf-related misunderstandings.
What is wrong with the following code written in c language?
I encountered a segmentation fault. what is it?
int a[2];
for(i=0;i<2;i++)
{
scanf("%d",a[i]);
printf("%d",a[i]);
}
Why couldn't it run? leave about declarations. Does scanf have any delay problems?
This:
scanf("%d",a[i]);
is wrong. The %d format specifier requires a pointer to where the value should be stored after conversion, i.e. it should be:
scanf("%d", &a[i]);
This is required since otherwise you pass the value of a[i] to scanf(), giving it no way to change the value. By passing the address of the value, scanf() can simply write to the provided memory address to change the value that is stored there. With printf(), you don't want your values to be changing, so passing them directly to printf() is fine.
Also, conversions (like many other forms of I/O) can fail, so you should check the return value before relying on the conversion having succeeded:
if( scanf("%d", &a[i]) == 1 )
printf("%d\n", a[i]);
You should probably read the manual page for scanf() a couple more times. :)
Pass the address of a[i] to scanf instead of the value of a[i].
scanf("%d",&a[i]);
I have the following code which stores string-input from a user N times in a multidimensional array. And then print out the second element.
main()
{
// Array to store 10 strings, 20 characters long.
char strStorage[10][20];
printf("\nEnter how many strings: ");
scanf( "%d" , &num);
fflush(stdin);
for ( count = 0 ; count < num ; count++)
{
printf("Enter a string: ");
gets(strStorage[count]);
fflush(stdin);
}
printf("%s", strStorage[2]);
Last line prints out garbage. The user-input is not visible inside the garbage hence either my element access is wrong or my storage is wrong. Can anyone help me with regards to what is the problem?
Thanks in advance...
strStorage[2] is the third string, so if num is less than 3, you won't initialize it and it will contain garbage.
scanf("%d", &num); doesn't ensure that num contains a value. Perhaps it'd be wise to check the return value of scanf to ensure it read 1 value, like this: if (scanf("%d", &num) != 1) { puts("Error reading integer"); }
While we're on this topic, I presume num and count are declared as an int, and you've hidden the declarations from us. Tsssk! Do you want our help? If so, then make your code compilable! Do you really think int is suitable for storing indexes to arrays? It's possible that they might have negative values. I'd suggest using size_t, instead, and the %zu format specifier tells scanf to expect a size_t value from stdin.
... and what happens when that size_t contains a value greater than the number of elements in your array? I suggest researching variable length arrays.
fflush(stdin); is nonsense because fflush defines behaviour for files open for output, and stdin is a file open for input only. That's sort of like flushing the toilet and expecting the waste to come out of the bowl, rather than going down through the S-bend. Perhaps you mean to discard the remainder of a line, because you've read the data you need from the start of it. Something like for (int c = getchar(); c >= 0 && c != '\n'; c = getchar()); might work.
Don't use gets. Use fgets(strStorage[count], sizeof strStorage[count], stdin); instead, to ensure that no buffer overflows occur.
There, I think I covered just about every bit of undefined behaviour and nit-picky stuffs.
I'm writing a program in C that displays a menu that asks the user to make a decision.
I want to bring up the menu multiple times in the program so I put it into function.
Each choice has a number associated with it:
(1) Add
(2) Subtract
The function displays the menu and then then I scanf the int response to a local variable and then return the variable (I of course declare the variable at the beginning of the function).
int function ()
{
int choice;
// *insert print menu code here*
scanf(" %i", &choice);
return choice;
}
Can I make this shorter by somehow doing a: return scanf(" %i", stdin);
I'm not sure if stdin would be the right choice, but that's what searching tells me.
Sure you can:
int scanInt(void) {
int result;
return (scanf(" %i", &result), result);
}
But is it useful? Probably not.
Note that this might look like undefined behaviour at first glance, because you're writing and reading from the same memory location in one expression. But it is not, as the comma operator introduces a sequence point.
You can't do this with scanf: you'd be returning the return value of scanf, which only indicates the number of items successfully read. If you need to return choice then you'll need to call scanf to fill choice and return it in two separate steps.
Another point here is that you should check the return value of scanf: it will fail if it's unable to convert the input. In your code, scanf will fail if the input is not an integer.
Furthermore, scanf reads from stdin - standard input - by default, you can't pass that as an argument unless you're using fscanf, which otherwise behaves in the same way.
Have you looked at using fgets for your input? It does return the next input line, which would allow you to do the read in the return statement since fgets returns the next line of input as a string. But you'd still need to parse the input yourself, which should probably happen within your function. In any case, fgets is typically a better choice for user input because it separates reading the input from parsing it, and avoids problems when using scanf due to input that doesn't match your format string.
You can, sort of -- but don't.
scanf returns the number of items scanned. You can't make it return the value of one of the scanned items.
return scanf(" %i", &choice), choice;
This uses the comma operator (not to be confused with the comma delimiter between function arguments), which evaluates both operands and yields the result of the right operand.
But there is no good reason to do this. There is no great virtue in making your source code more compact like this. The multi-line form is clearer, and it's easier to modify by adding error handling (what happens if the user enters something other than a number?)
Or you could write your own function that calls scanf and returns the value you want, but that still doesn't address the issue of error handling.
And if your goal is simply to put them on one line:
scanf(" %i", &choice); return choice;
But again, this is not an improvement.
No, you can't with scanf. The function needs a memory location to store the result, and doesn't return it. So you just have to live with the extra code.