Problems with array and scanf function working together - c

I am a beginner. I want to write a program, that will guess a number, which user picked. In general, user pick a number within the given limit, the program will generate a random number within same limit, ask user if it's a right number, Y/N answer, program reads it, then ask if user's number is bigger or smaller, reads the answer and pass this information to 2 additional functions.
(I didn't finish those yet, but the idea is that it will divide the rest of numbers in 2, ask again, bigger smaller, divide it once again by 2 and so on, till we get the answer.)
The problem is, that even if I use a simplest array of type char, I cannot get it work. The answer of the computer is if I didn't book enough memory for one of the arrays.
I'm still 2 chapters away from the arrays theme in my book, I just wanted to write this program. What I use here is what I've learned so far, so if it's possible, don't use any more complex functions and features of C in your answers.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
int bigger(int number, int limit);
int lower(int number, int limit);
int main(void) {
system("COLOR B0");
const int Hlimit=100;
const int Llimit=0;
char alowwed_answer[]={'>','<'};
char answer[2];
char alowwed_answerYN[]={'Y', 'N'};
char answerYN[2];
srand((unsigned)time(NULL));
int numberTOguess;
printf("\r\nEnter your number from %i to %i, "
"and I will try to guess!: ",Llimit,Hlimit);
while(scanf("%i",&numberTOguess) )
{
int check=rand()%Hlimit;
printf("\r\nyour number is - %i Y/N?",check);
scanf("%c",&answerYN[0]);
printf("answer is %c\r\n", answerYN);//this line is for checking;
int check_answ=strcmp(answerYN[0],alowwed_answerYN[0]);
printf("check answer is %i",check_answ);//this line is for checking;
if(check_answ==0)
{
printf("I did it!");
break;
}
else if(strcmp(answerYN[0],alowwed_answerYN[1])==0)
{
printf("\r\nyour number is bigger '>' or smaller '<'?: ");
scanf("%c",&answer);
if(strcmp(answer[0],alowwed_answer[0])==0)
{
bigger(check, Hlimit);
}
else if(strcmp(answer[0],alowwed_answer[1])==0)
{
lower(check, Llimit);
}
}
}
printf("\r\nI did it!");
return 0;
}
int bigger(int number, int limit)
{
printf("it is bigger!");//I will finish this part as soon as I will get first part working.
return 0;
}
int lower(int number, int limit)
{
printf("it is lower!!!");//I will finish this part as soon as I will get first part working.
return 0;
}
Update
Thanks, I took your advice and change the statement type to SWITCH. But it still doesn't work properly. Somehow, nested switch doesn't function at all.
Look at the code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
int bigger(int number, int limit);
int lower(int number, int limit);
int main(void) {
system("COLOR B0");
const int Hlimit=100;
const int Llimit=0;
char answerBL;
char answerYN;
srand((unsigned)time(NULL));
int numberTOguess;
printf("\r\nEnter your number from %i to %i, "
"and I will try to guess!: ",Llimit,Hlimit);
while(scanf("%i",&numberTOguess) )
{
int check=rand()%Hlimit;
printf("\r\nyour number is - %i Y/N?",check);
scanf("%c",&answerYN);
switch(answerYN)
{
case 'Y':
printf("I did it!");
break;
case 'N':
printf("\r\nOk, your number is bigger '>' or smaller '<'?: ");
scanf("%c",&answerBL);
switch(answerBL)
{
case '>':
bigger(check, Hlimit);
break;
case'<':
lower(check, Llimit);
break;
}
default:
printf("Y or N?");
}
}
printf("\r\nEND!");
return 0;
}
int bigger(int number, int limit)
{
printf("it is bigger!");
return 0;
}
int lower(int number, int limit)
{
printf("it is lower!!!");
return 0;
}
Edit
Problem is solved, I found the reason and how to fix it. Here it is, from another topic
The basic problem is that scanf() leaves the newline after the number in the buffer, and then reads it with %c on the next pass. Actually, this is a good demonstration of why I don't use scanf(); I use a line reader (fgets(), for example) and sscanf(). It is easier to control.
You can probably rescue it by using " %c" instead of "%c" for the format string. The blank causes scanf() to skip white space (including newlines) before reading the character.
But it will be easier in the long run to give up scanf() and fscanf() and use fgets() or equivalent plus sscanf(). All else apart, error reporting is much easier when you have the whole string to work with, not the driblets left behind by scanf() after it fails.
You should also, always, check that you get a value converted from scanf(). Input fails — routinely and horribly. Don't let it wreck your program because you didn't check.
answered Mar 5 '12 at 7:05
Jonathan Leffler

The function strcmp expected two pointers as arguments, pointers to the first characters of a null-terminated byte strings.
With e.g.
strcmp(answerYN[0],alowwed_answerYN[0]);
you have two major problems:
The array answerYN is (partially) uninitialized, its contents is (also partially) indeterminate. That means answerYN[1] is likely not the string terminator as needed.
alowwed_answerYN[0] is a single char not a pointer to a string. This should have given you a warning about invalid conversions or similar.
If you just want to compare characters, use normal comparison for equality ==, as in answerYN[0] == alowwed_answerYN[0].
Or why not skip alowwed_answerYN completely and plainly use the explicit character literal as in answerYN[0] == 'Y'. That's even clearer than using an array for the 'Y' and 'N'.

Related

Why am I not able to enter desired number of inputs?

The problem is about taking input of strings x number of times using an array of pointers. x is the value entered by the user. I wrote the following code for the same. But the program is taking only x-1 inputs.
I have inserted fflush(stdin) because I think the scanf is consuming an enter first but I don't know from where.
I have tried using gets but with no use.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
//code to take input in an array of pointers
int x,i,j,length;
char ch[50],*t;
printf("How many names you want to sort:\n");
scanf("%d",&x);
char *names[x];
char *p;
printf("Enter the names:\n");
for(i=0;i<x;i++)
{
fflush(stdin);
scanf("%[^\n]s",ch);
length = strlen(ch);
p = (char *)malloc((length+1) * sizeof(char));
strcpy(p,ch);
names[i] = p;
}
return 0;
}
Why bother with complex format strings if you don't have to? Use fgets.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void err(const char * msg) {
fprintf(stderr, msg);
exit(1);
}
int main()
{
int x,i;
char ch[50];
printf("How many names you want to sort:\n");
if(!fgets(ch, 50, stdin)) err("Error reading line");
if(sscanf(ch, "%d",&x) != 1) err("Could not read integer");
// Better than using VLA
char **names = malloc(x*sizeof(*names));
if(!names) err("Error allocating names");
printf("Enter the names:\n");
for(i=0;i<x;i++) {
if(!fgets(ch, 50, stdin)) err("Error reading line");
ch[strcspn(ch, "\n")] = 0; // Remove newline
if(!(names[i] = strdup(ch))) err("Error duplicating string");
}
for(int i=0; i<x; i++)
printf("name %d: %s\n", i, names[i]);
}
Whenever a function has a return value that may indicate an error you should ALWAYS check it, and here that is the case for malloc, fgets, strdup and sscanf and. Read the documentation to find out what it actually returns to see how to check for errors. sscanf returns the number of successful assignments, and the other three returns a pointer which is NULL on failure.
You wrote in the comments that you are learning from the book "Let us C". A better fitting title would be "How to not code C". I've had a quick look at it and, it is really really bad. Apart from teaching very outdated C, it also teaches very bad habits in general, and many of the things you can read is completely WRONG. Actually, the majority of questions about C can be traced to that book, or at least could have. Two prime examples is that it consistently avoids very important stuff, such as error checking functions like scanf and malloc. I have not read every line, but I think it does not even mention how to error check scanf even once. It also uses the function gets which is not only deprecated but completely removed from newer C standards because it is so dangerous. It also says that you can modify a string literal, which is undefined behavior in C.

why doesn'y this code work?

This question is regarding the SPOJ tutorial problem :
Your program is to use the brute-force approach in order to find the Answer to Life, the Universe, and Everything. More precisely... rewrite small numbers from input to output. Stop processing input after reading in the number 42. All numbers at input are integers of one or two digits.
I want to run the program without if -else statements but the program doesn't work. Can someone please tell me what am I doing wrong?
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i;
while (i != 42)
{
putchar(i);
i = getchar();
}
exit(0);
}
Here is a quick and dirty way of getting the result that you want.
Since you want the user to enter number (which is composed of multiple characters), you will want to use scanf() instead of getchar().
scanf() documentation : http://www.cplusplus.com/reference/cstdio/scanf/
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i = 0;
while (i != 42)
{
scanf("%d", &i);
printf("You have entered : %d\n", i);
}
printf("You have successfuly entered 42!\n");
exit(0);
}
Hope this helps.

Input several ints on one line, return number of ints

I'm learning C after having learned Java (among other languages), and I'm somewhat confused about how to handle this simple problem. I need to write a program that will take input in the form of one line. For example, 5 2 75 43 68 (only ints), and I need to return the number of ints, their sum, and the number of positive and negative numbers.
The problem is that the number of inputs is, obviously, variable--there may be one int or seven, but all will be on one line. I'm not sure how to use C to handle the variable number of inputs. Can someone point me in the right direction?
TO handle variable number of inputs, you need to loop and scanf until you press (Ctrl+D)
Here is an example:
int n,sum=0,count=0;
while(scanf("%d",&n)!=EOF)
{
sum=sum+n;
count++;
}
printf("sum=%d,count=%d",sum,count);
Note: When you press Ctrl+D, scanf returns -1, and hence the process of taking inputs terminates!
Cheers!
Input a string, then search for spaces, then convert each number at that position and add it to count and sum. This way, you only need to have the upper limit on the buffer where you're inputting the line; you don't use an array, so you don't need to either limit the number of ints nor do you have to mess with dynamic allocation.
EDIT: In Kerrek SB's format, combine fgets, strchr and strtol. :P
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char buffer[200];
int numbers[100];
int main() {
char *ptr;
int cnt = 0;
fgets(&buffer[0], 200, stdin); // Get the string
ptr = strtok(buffer, " "); // Split in every space
do {
printf("Number %d: %s\n", cnt, ptr);
numbers[cnt] = strtol(ptr, NULL, 0); // Grab number
cnt++;
} while((ptr = strtok(NULL, " ")));
printf("Total numbers: %d\n", cnt);
}

'fgets' runs after 'printf'

I'm slowly learning C. I read this page about input and output dealing with strings here: http://www.cprogramming.com/tutorial/c/lesson9.html
In the last code example, fgets is used to get and assign the input to a variable to the char array name. I tried implementing something similar in my own program.
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
/* This is my very first C program! */
bool test=true;
/* Function Prototypes */
int mult(int x, int y);
/* Structures */
struct Person {
int age;
char name[256];
};
/* Complicated Array ;P */
struct Person *FirstPeriod[22];
char FakeString[100];
void PracticeStrings()
{
int i;
fgets(FirstPeriod[0]->name, 256, stdin);
for (i=0;i<256;i++)
{
if (FirstPeriod[0]->name[i]=='\n')
FirstPeriod[0]->name[i]='\0';
}
printf("\n\nHello Student 0: %s",FirstPeriod[0]->name);
}
int main()
{
struct Person DadeLamkins;
DadeLamkins.age=16;
int numb;
int x;
int *numb_address=&numb;
numb_address=malloc(sizeof(*numb_address));
FirstPeriod[0]=&DadeLamkins;
if (true)
printf("-__- \n\n");
printf("Please enter a number: ");
scanf("%d", &numb);
switch (numb) {
case 0:
printf("Dude, 0 is lame...\n");
break;
case 7:
printf("Dude, 7 is my favorite number!\n");
break;
default:
printf("You entered %d\n", numb);
break;
}
for (x=0;x<numb+1;x++) {
printf("\n::# %d",mult(x,2));
}
printf("\n\n%d",numb_address);
free(numb_address);
numb_address=0;
PracticeStrings();
getchar();
return 0;
}
int mult (int x, int y)
{
return x*y;
}
The PracticeStrings function on line 26 is the issue currently. When I compile, it displays Hello Student 0: before accepting the input (from fgets). I'm using Code::Blocks to compile.
Any help would be appreciated!
Edit...
Hahaha, yes, I understand that my program is inefficient and very silly. As you can tell, it doesn't really accomplish much. It is mostly just something to shove what I'm currently learning and try to apply things without actually rewriting the code examples (what do I learn if I copy word for word?). Anyways, thanks for the help! I guess that does make sense! It is too bad that my tutorials didn't mention that, I'm sure it is something that just takes a little bit of a higher understanding. I'm sure that the tutorial writer didn't expect anyone to mix the functions in the way I did.
Thanks a ton guys! Hopefully I can get used to this. I've done lots of scripting and plenty in the .net languages, hopefully I can add C to this list :)
It is because when you read the number:
scanf("%d", &numb);
stdin still has \n left in the buffer. So when you call PracticeStrings() and subsequently:
fgets(FirstPeriod[0]->name, 256, stdin);
You read \n and end up with
FirstPeriod[0]->name[i] == '\0';
Further, as you are learning, learn to validate :)
I.e.:
if ((foo = malloc(blah)) == NULL) {
... err ...
And even more critical:
if (scanf(..) != number_of_items_i_want) {
... did not get a number, or what ever I wanted ...
etc.
I think your issue is due to the behavior of your console, and your scanf() call.
The default setting for your console is probably line buffering. That means that nothing you type on your terminal is sent to stdin until after you have hit the enter key.
However, your call to scanf() (in main()) is only grabbing the integer that you've typed - not the trailing carriage return. Your carriage return is still sitting, unread, in stdin until the fgets() call in line 26.
One way around that is to get scanf() to consume the trailing carriage return too:
scanf("%d%*c", &numb);
Which reads the integer from stdin into &numb, and reads (and discards) an extra character.
This all hilights one of the big problems with the use of scanf(), which is how to make it cope in the event that you get a string that you weren't expecting.
A safer way is to use a combination of fgets() and sscanf(). The former will let you read a string from a file (as you've done), and the latter will run a formatting string over it.
eg.
char temp[20];
fgets(temp, 20, stdin);
sscanf(temp, "%d", &numb);

Problem with character input by getchar() or getche()

When I compile the C codes (from Teach yourself C, 2nd edition-Herbert Schildt) written below in Borland C++ v5.02, I get a warning message as below:
"c61.c(7,6): Conversion may lose significant digits"
What's wrong?
#include "stdio.h"
main()
{
char ch;
ch = getchar();
printf(" You typed: %c", ch);
return 0;
}
Same problem with another example:
#include "conio.h"
#include "stdio.h"
main()
{
char ch;
printf("Enter a character: ");
ch = getche();
printf("\nIts ASCII code is %d", ch);
return 0;
}
getchar() returns an int, so that it can return non-character values like EOF. So when you store the return value in a smaller datatype, like a char, you are potentially losing information.
Schildt's books are commonly considered the worst available for learning C (or C++) and this is a good example of why. You would be well advised to get a better book, such as K&R.
The prototype for getchar is:
int getchar (void);
It returns an int because it needs to return EOF which is not a character.
Expanding on that, the function needs to be able to return any valid character, as well as being able to return a special "character" indicating that you're reached the end of file (or an error has occurred).
Since a char data type can only hold one of the characters, there would be no way to indicate this end of file if all the function returned was a char. That's because, if you selected one of those char values to represent end of file, you would not be able to tell the difference between the end of file and the actual character.
For example, let's choose 'A' to indicate end of file. When you actually get back an 'A' from getchar(), how will you know whether you've reached the end of file or whether the user actually entered 'A'?
To get around this, many functions that give you back a char will actually give you an int and use one of the integer values which don't have an actual char equivalent (such as -1).
In that case (assuming an 8-bit char), you would get back either a -1 if you've reached the end of the file or a value from 0 through 255 inclusive representing the character entered.
And you need to get yourself both a more modern book and a more modern compiler:
#include <stdio.h>
int main (void) {
int ch = getchar();
if (ch != EOF)
printf("You typed: %c\n", ch);
return 0;
}
Why anyone is still using Borland is this day and age (where gcc is both just as cheap and much better) is beyond me.
What about this alternative program? It works fine.
#include <stdio.h>
main()
{
char ch;
getchar();
printf("Enter the character: ");
scanf("%c", &ch);
printf(" You typed: %c\n", ch);
return 0;
}
Please leave some comments.

Resources