c program taking multiple inputs instead of one input [duplicate] - c

I'd like to understand why the program allows me to input 3 integers when I have defined SIZE as 2. And when it returns the array it only returns two numbers NOT the three I have entered.Thanks for your help.
//C How to Program Exercises 2.23
#include <stdio.h>
#include <conio.h>
#define SIZE 2
int main (void){
int myArray[SIZE];
int count;
printf("Please enter 5 integers\n");
for (count=1;count<=SIZE;count++){
scanf("%d\n",&myArray[count]);
}
for (count=1;count<=SIZE;count++){
printf("The values of myArray are %d\n",myArray[count]);
}
getch();
return 0;
}

Your loops should be
for (count=0;count<SIZE;count++)
Array indexing is 0 based in C.
Since you have a whitespace chatacter (\n) in scanf() call, it waits for you input a non-whitespace character to complete each call. Remove the \n:
for (count=0;count<SIZE;count++){
scanf("%d",&myArray[count]);
}

C arrays are indexed starting from 0, not from 1. C does not automatically perform bounds checking on array accesses, and indeed, your code is well-formed. However, its runtime behavior is undefined on account of its using an array element expression to write outside the bounds of that array, and, separately, on account of its using an array element expression to read outside the bounds of that array.
Inasmuchas the program definitely exhibits undefined behavior on every run, absolutely nothing can be said about what it should do. If in practice you observe the input loop iterating thrice, then a likely explanation is that the second iteration overwrites the value of the count variable. Given the order in which the variables are declared, this is a plausible manifestation of the undefined behavior in play.
The output loop, on the other hand, iterates exactly the number of times you told it to do: once with count == 1, and once more with count == 2. This is by no means guaranteed given the general undefinedness of an execution of your program, but it is about the least surprising behavior I can think of.

why the program allows me to input 3 integers
This loop runs exactly 2 times:
for (count=1;count<=SIZE;count++){
scanf("%d\n",&myArray[count]);
}
But as you used \n in the scanf(), this scanf() waits until you give any whitespace.
Proper Input code:
for (count=0;count<SIZE;count++){
scanf("%d",&myArray[count]);
}
And when it returns the array it only returns two numbers
Your original output code prints first number correctly, But your second number is garbage value.
Proper Output Code:
for (count=0;count<SIZE;count++){
printf("The values of myArray are %d\n",myArray[count]);
}
So Full Code goes like this:
//C How to Program Exercises 2.23
#include <stdio.h>
#include <conio.h>
#define SIZE 2
int main (void){
int myArray[SIZE];
int count;
printf("Please enter 5 integers\n");
for (count=0;count<SIZE;count++){
scanf("%d",&myArray[count]);
}
for (count=0;count<SIZE;count++){
printf("The values of myArray are %d\n",myArray[count]);
}
getch();
return 0;
}

Related

Use sscanf to process variable-format output

This is a program ,15.5,in the book called Pointers On C.I can't understand what this program want to do.
#include<stdio.h>
#include<stdlib.h>
#define DEFAULF_A 1
#define DEFAULF_B 2
void function(char *buffer)
{
int a,b,c;
if(sscanf(buffer,"%d %d %d",&a,&b,&c)!=3)
{
a=DEFAULF_A;
if(sscanf(buffer,"%d %d",&b,&c)!=2)
{
b=DEFAULF_B;
if(sscanf(buffer,"%d",&c)!=1)
{
fprintf(stderr,"Bad input:%s",buffer);
exit(EXIT_FAILURE);
}
}
}
}//***the title of the program is Use sscanf to process variable-format output***
If I suppose the first three number in buffer is 1,2 and 3.
List item
The sscanf at the second if assigns 1 to B that should have been assigned to A and assigns 2 to C that should have been assigned to B.So why not just throw out the &c and leave the &a in sscanf,like this
c=DEFAULF_A;
if(sscanf(buffer,"%d %d",&a,&b)!=2)
List item
And why does the exit(EXIT_FAILURE) appear in the third if?When the exit(EXIT_FAILURE) appear in the third if,it mean there is a problem with the first read and the second and the third reads don't know.But when it comes this case sscanf(buffer,"%d %d %d",&a,&b,&c)!=3,the program is also wrong.
List item
So what this program want to do?
Due to I just started to learn CS,I only konw a little about C language,and lack other basic computer knowledge,please answer in a way that is easy to understand.Thanks in advance.
This is a example in Pointers On C .This program might correspond to this sentence that "the latter is used to convert the expected number of values.
[] The sscanf at the second if assigns 1 to B that should have been assigned to A and assigns 2 to C that should have been
assigned to B.So why not just throw out the &c and leave the &a in
sscanf,like this
c=DEFAULF_A;
if(sscanf(buffer,"%d %d",&a,&b)!=2)
Because that's (apparently) not the desired behavior. The program is assigning read values to the rightmost subset of variables (a, b, c), so if only two values are provided then they go to b and c, and if only one is provided then it goes to c. The variables that don't get read values assigned to them are assigned default values instead. Your proposed alternative does not achieve the same thing.
And this is in fact the distinguishing characteristic of the function presented -- the "trick", if you will. It would indeed be simpler to write a straight left-to-right style matchup of values to variables.
Nevertheless, the function is needlessly complicated. Myself, I would not write it with three separate sscanf calls, because you can get everything you need from just one. I would write the function something like this:
#define DEFAULT_A 1
#define DEFAULT_B 2
void function(char *buffer) {
int a, b, c, num_fields;
num_fields = sscanf(buffer, "%d %d %d", &a, &b, &c);
switch (num_fields) {
case 3:
// three values read and assigned. nothing to see here.
break;
case 2:
// only two values read (into variables 'a' and 'b')
// shift them to the correct variables and assign a default to 'a'
c = b;
b = a;
a = DEFAULT_A;
break;
case 1:
// only one value read (into variable 'a')
// shift it to the correct variable and assign defaults to the others
c = a;
b = DEFAULT_B;
a = DEFAULT_A;
break;
default:
fprintf(stderr, "Bad input: %s\n", buffer);
exit(EXIT_FAILURE);
}
}
[] And why does the exit(EXIT_FAILURE) appear in the third if?When the exit(EXIT_FAILURE) appear in the third if,it mean there is
a problem with the first read and the second and the third reads don't
know.But when it comes this case sscanf(buffer,"%d %d %d",&a,&b,&c)!=3,the program is also wrong.
The return value of sscanf reports on two things:
how many scanf directives resulted in values being successfully read from the input, converted to the indicated data type, and assigned to variables; and
whether any kind of system error was encountered (very unlikely for sscanf(), but this is shared with scanf(), for which it is a genuine possibility).
You seem to have the second one in mind, but it is the first that the program is mainly relying upon. It is using the return value to determine how many of the variables were assigned values. That the first attempt does not assign all three does not imply that the second will not assign two, or the third, one. But of course you're right that the program is somewhat redundant. As I demonstrate above, only one sscanf() call is needed.
[] So what this program want to do?
Nitpick: it's just one function, not a complete program.
Technically, because it doesn't do anything with the values it parses out of the string, all it does is report on whether the string pointed to by the function argument starts with a text representation of at least one decimal integer, optionally preceded by any number of whitespace characters (spaces, tabs, etc.). If so, it prints nothing. If not, it prints an error message.
But what you're probably looking for is the explanation I provided in response to your first numbered question.
Seeing how you are essentially asking 'What does this program' do: It is essentially performing a 'default initialization for not entered values'.
Another (more efficient) way to achieve (much) the same thing is:
#include<stdio.h>
#include<stdlib.h>
#define DEFAULF_A 1
#define DEFAULF_B 2
void function(char *buffer)
{
int a,b,c;
switch (sscanf(buffer,"%d %d %d",&a,&b,&c))
{
case 1:
b = DEFAULF_B; //Only one has been entered, assign default to 'b'.
//Falls through
case 2:
c = DEFAULF_A; //Only two have been entered, assign default to 'c'.
//Falls through.
case 3: break; //All three have been entered, do nothing.
default:
exit(EXIT_FAILURE); //None have been entered -> Abort the program.
break;
}
}
If buffer contained 3 numbers, all three numbers are kept and no defaults are applied.
If buffer contained 2 numbers, the two numbers are kept (in your code that's b and c, in mine it's a and b) and DEFAULF_A is assigned to the remaining variable.
If buffer contained 1 number, that number is kept (c for you, a in my example) and the other two get assigned DEFAULF_A and DEFAULF_B respectively.
If buffer contained no number at all, your program gets terminated with the return code 'EXIT_FAILURE', which a calling program could fetch.
The program examines contents from a buffer, and tries to read three values from it, for example:
1 2 3
If the first sscanf finds three numbers, it reads them all. If only two are found, it assigns default value to a and tried to read two numbers. If only one is found, it assigns default value to b and tries to read one number. If there are no numbers, the program exits, because there is no default value for c.
So if we reach exit(), it means there were neither 3, 2, or 1 numbers in the buffer. If one of the if clauses succeeded, further ones are not executed.
It is important to realize that sscanf always starts from the beginning of the buffer. So if it reads for example 1 2 in the first call, but cannot find the third one, the buffer still contains the same data during the second call, and two numbers can be read.
Regarding your question 1: Why are two numbers considered as "b and c", rather than "a and b"? This is simply the way the programmer wanted the program to work. They could have as easily set a default value for c and considered the two numbers as "a and b".
Regarding your question 2: What if the output is completely invalid, and the third read will fail? In that case, we know that the first and second reads will fail as well, so we can safely put the error handling after the third one.

Limiting the type length of the user on C

My code asks a the 10 digit number, it reads it as a string, pass it to another function that checks if the user's input is a real number and has no characters or symbols with ASCII, and then if it's good, with atof it changes the string into a number for a variable.
I want the user to only introduce 10 digits/characters on the input console, I mean, if the user would put a 11 character for example, the console just don't grab it, or in the case this is impossible for C, make that if the user put more than 12 characters on the input, then the program launches an error message saying it exceeds the limit, the problem is, when i tried to use this method, for example if i put some big numbers like a 40 digit number, then the program goes crazy and send just incomprehensible results like "1.#J", or if I put a character in middle of the numbers, then it sends the corresponding error message i set for the user to not put characters, but it still grabs part of the number and accept it as it is nothing wrong, here's the main of code I tried:
int main() {
char chain[10];
float N;
int valid=0;
do{
printf("introduce real numbers: ");
fgets(chain, sizeof(chain), stdin);
if( chain[strlen(chain)-1] == '\n')
chain[strlen(chain)-1] = '\0';
valid=validate_numbers(chain);
}while(valid==0);
N=atof(chain);
printf("float number is: %.2f", N);
getche();
return 0;
}
Here's the rest of the code for more extense check: Pastebin
And sorry if there's some novice errors or the question is plain simple, im quite new programing.
Change this:
char chain[10];
to this:
char chain[11]; // +1 for the NULL terminator
since C-strings should be NULL terminated, thus we need one cell reserved for the NULL-terminator in our array (which will store our string).
I mean, if the user would put a 11 character for example, the console just don't grab it
Not possible in C.
or in the case this is impossible for C, make that if the user put more than 12 characters on the input, then the program launches an error message saying it exceeds the limit.
Yes, let's do that! Read the string, and if the length of it is more than 10 characters, then print an error message.
Allow chain array to be of size 12 (10 for the maximum length of the valid input, 1 for an extra character (if any) and 1 for the NULL-terminator), so that we can store the extra character, if any.
Example:
#include <stdio.h>
#include <string.h>
int main(void)
{
char chain[12];
printf("introduce real numbers:\n");
fgets(chain, sizeof(chain), stdin);
chain[strcspn(chain, "\n")] = '\0';
if(strlen(chain) > 10)
{
printf("Error: Maximum length of chain is 10! Exiting..\n");
return 1;
}
return 0;
}
Note: You could use EXIT_SUCCESS and EXIT_FAILURE, instead of plain numbers (1 and 0 respectively): Should I return 0 or 1 for successful function?
Irrelevant to OP's question: In the full version of your code though, there is a plethora of problems, such as this top line of code int valid=validate_numbers(char number[]);, which wishes to declare the method. It should be just validate_numbers(char number[]);. The same holds true for the definition of the method too. Make sure you go through all your code again, and read the messages the compiler gifts to you. :)
What about using scanf instead of fgets? This should read 9 characters and save them as a string:
scanf("%9s" , &chain)
I'd suggest reading https://en.m.wikipedia.org/wiki/Scanf_format_string and man pages as well.

Array Declaration causing weird behavior with while loop

I have recently encountered very weird behaviour with my c program. I gutted out most of the code just to isolate where the issue is happening for you guys.
The purpose of the program in its current state is to read in jobs from a txt file and print the contents to the screen. Here it is:
#include <stdio.h>
int main(){
char* user;
char process;
int arrival;
int duration;
scanf("%*[^\n]"); //skipping header in the file.
while(!feof(stdin))
{
scanf("%s\t%c\t%d\t%d\n", user, &process, &arrival, &duration);
printf("%s\t%c\t%d\t%d\n", user, process, arrival, duration);
}
int x[5]; //<----- Causing the weird behaviour
}
The file I pipe into it is:
User Process Arrival Duration
Jim A 2 5
Mary B 2 3
Sue D 5 5
Mary C 6 2
The issue that I'm running into is whenever I declare the int x array, whether it is at the bottom or top of my code, the while loop enters an infinite loop or the program seg faults.
It will go into an infinite loop or seg fault depending on the size I declare the array at. For example, if I declare the array to be size 5, it enters an infinite loop. However, if I declare the array to be size 2, it will seg fault.
I am compiling my program by running:
gcc -o myprog myprog.c
and I am piping the file by running:
cat jobs.txt | ./myprog
It is also worth noting that the program runs fine without the int x array declaration.
I am completely stumped as to what might be the issue, any thought?
You have an undefined behavior because of the pointer user which is not initialized. user must point to a memory area capable of storing what you want (see malloc() for example).
As you have found from the other answer, your initial problem is with char *user; which declares a character pointer that is uninitialized (e.g. it does not point to any valid block of memory). While you can dynamically allocate with malloc, calloc, or realloc, that may be an over-complication for your circumstance.
All you really need is to declare a character array sufficient to hold the user names. 16 chars is more than sufficient here.
Next while (!feof(fp)) is almost always wrong. (see link in my comment). scanf provides a return of the number of valid conversions that take place. In your case, with "%s..%c..%d..%d" (4-conversion specifiers), a return of 4 will indicate that no matching or input failure occurred. So instead of your feof check, just use the scanf return, e.g.
scanf("%*[^\n]"); //skipping header in the file.
while (scanf ("%15s %15s %d %d", user, process, &arrival, &duration) == 4)
printf ("%s\t%c\t%d\t%d\n", user, *process, arrival, duration);
(note: for the simplified scanf format string "%15s %15s %d %d", arrival is declared as a character array (see below) and read as a string (to take advantage of leading white-space skipping) and then *arrival is used to pick off the character. This provides a bit more robust way to read your input in the event your input is space separated instead of *tab separated)
To avoid using magic numbers in your code (e.g. 16), declare a constant if you need one for the max characters in your arrays, e.g.
#define MAXC 16
int main (void) {
char user[MAXC] = "", process[MAXC] = "";
note: it may look like "%15s %15s %d %d" breaks this rule, but sadly, there is no way to include a constant of variable in the scanf field width specifier that protects against reading more than 15 chars into your arrays -- remember, you must leave room for the final character -- the nul-terminating character.
Putting it altogether, you could do something like the following:
#include <stdio.h>
#define MAXC 16
int main (void) {
char user[MAXC] = "", process[MAXC] = "";
int arrival, duration;
scanf("%*[^\n]"); //skipping header in the file.
while (scanf ("%15s %15s %d %d", user, process, &arrival, &duration) == 4)
printf ("%s\t%c\t%d\t%d\n", user, *process, arrival, duration);
return 0;
}
Example Use/Output
$ ./bin/scanf_usr_arriv <dat/userprocarriv.txt
Jim A 2 5
Mary B 2 3
Sue D 5 5
Mary C 6 2
You may also want to consider reading all "lines of input" with a line-oriented input function like fgets and then calling sscanf on the resulting buffer to parse each of the variables. This has the benefit of allowing separate validation on the line being read, and then an independent validation on the parse of each variable from the line.
Look things over and let me know if you have any questions.

Using getchar() and malloc() together

I found a C Program whose purpose is to input a string while using dynamic memory allocation.
However I am having difficulty understanding the logic behind it.
#include <stdio.h>
#include <stdlib.h>
#define MAX 10
int main(void)
{
char *A;
int max_int=0;
printf("Enter max string length: ");
scanf("%d",&max_int);
while ((getchar())!='\n');
A=(char *)malloc(max_int+1); //room for null char
printf("Enter string: ");
fgets(A,max_int,stdin);
}
What is the purpose of while ((getchar())!='\n'); ? It seems redundant to me, since your only inputing a number before it gets called.
while ((getchar())!='\n');
The above line is used to flush anything on the line not read by scanf, for example non-digits and spaces, so the next input starts in a new line.
Also:
scanf-call should check the number of assigned matches (0 matches is possible.
the result of malloc should never be cast (that just hides bugs).
the result of malloc should be checked for NULL. (Warning: Undefined Behavior)
fgets expects the buffer length and guarantees 0-termination. Passing one less means you get a shorter string.

How to test my program against an input test case file

I was participating in some coding contests and luckily my code also ran. However my solution was not expected because i was wrong with the pattern of taking input.
The question involved taking in an integer as an input and performing some operation and returning a different or same integer. I do not have any problem with the program, I just don't know how to code so as to take inputs like this
Input
The input will contain several test cases (not more than 10).
Each test case is a single line with a number n, 0 <= n <= 1 000 000 000.
It is the number given as input.
Output
For each test case output a single line, containing the integer returned.
Example
Input:
12
2
Output:
13
2
My code is
#include <stdio.h>
int functionReturningInteger(int n)
{
// implementation
........
return num;
}
int main(void)
{
int number;
//printf("Enter the number: ");
scanf("%d",&number);
printf(functionReturningInteger(number));
return 0;
}
How am i supposed to know how many inputs they will give ( although they do provide a maximum limit). And if i use an array to store these inputs whose size is equal to the maximum limit, how do i check the size of an integer array in c ?
I will appreciate anybody helping out with a small piece of code. Also if am able to test it against an input test file and generate an "output.txt" (output file). I already have the desired output file "des.txt". Then how can i match whether both the files are same or not ?
#include <stdio.h>
int scanned;
while((scanned = scanf("%d", &number)) != EOF) {
printf("%d\n", functionReturningInteger(number));
}
If scanf detects the end of input before a successful conversion, it returns EOF.
For the other questions, redirect input and output,
$ ./your_prog < input.txt > output.txt
and compare
$ comp output.txt des.txt
You could read line by line until there is nothing to read from file. This way you don't need to know how many inputs is given.
There is no default way to track array size in C.
To match files you can use diff on Linux\Unix os.

Resources