my do, while loop not working as i meant :( ( C language) - c

hi guys Im about to finish some c basics course and am ending it with a full calculator project.
at arrays part my following do while loop keeps looping over and over cant break the condition.
I tried to add exit();
also changed return(0) to return(EOF) but nothing happens.
this is the code:
#include <stdio.h>
int main()
{
int row_num,colm_num;
do
{
printf("PLEASE! choose Array 'A' Rank (maximum 4x4)==>\n\n");
printf(" 'A' rows= ");
scanf("%i", &row_num);
printf(" 'A' columns= ");
scanf("%i", &colm_num);
printf("Array 'A' set to rank = %ix%i i.e. (A[%i][%i]) \n\n)",row_num,colm_num,row_num,colm_num);
}
while(( scanf("%i", &row_num)==1 || row_num<=4||row_num>=0)||( scanf("%i", &colm_num)==1 || row_num<=4||row_num>=0)); //restriction for user input
return(0);}
I have to mention that this is not the full code but I run this in separate file to debug each section alone btw if there is better way to debug sections of the code than starting another c file tell me "am using codelite editor IDE" thanks all also am open for any beginners\efficient c coding advices I would be grateful ^^.

Your scanf condition (scanf("%i", &row_num)==1) doesn't do quite what you expect it to do. From the scanf manpage:
RETURN VALUE
These functions return the number of input items successfully matched
and assigned, which can be fewer than provided for, or even zero in the
event of an early matching failure.
You have one input item being matched, so scanf always returns 1 as long as the input was numeric, and you never can exit the loop because the condition remains true.
Call scanf to read row_num and col_num before the end of the loop body (checking the return value to signal an error to the user) and then directly check the value of those two variables in the condition.
Alternatively, you could use && instead to verify that scanf did indeed read one value, and check the value in the same condition, but this arguably creates an overly messy and hard-to-read condition.
I run this in separate file to debug each section alone btw if there is better way to debug sections of the code than starting another c file
The best option is to create separate functions, which you can call and test individually from main as you test. Once your code matures, you can put all the functions together, and continue to test and debug using tools such as your debugger.

Related

'comparison between pointer and integer' error for Phone Directory program

So I'm pretty new too C, and programming. I'm learning little by little. A friend of mine gave me a good idea for a first project. The goal is too allow the user too select a department (Phone Directory for a Casino), and once that department has been selected, it will show all the numbers for that department.
Eventually I want too add more too this, but for now, I'm going too keep it simple.
#include <stdio.h>
main()
{
printf("Please Select Department [Security, Food & Beverage, Hotel]\n");
char str[20];
gets(str);
if (gets(str) == 8)
{
printf("You have selected Security\n");
printf("218-760-1122, 218-760-5564\n");
}
else if (gets(str) == 5)
{
printf("You have Selected Hotel\n");
printf("218-443-9810");
}
else if (gets(str) == 15)
{
printf("You have selected Security\n");
printf("218-550-9818, 218-443-1231\n");
}
return 0;
}
The problem with this program is when I compile and build the program, it prints the "selection" part of the script, where get(str) is used. After I select which one I would like too use, it goes blank, and nothing is displayed, but the script itself is still running.
I'm really new too this, and I'm assuming its something too do with how I'm determining which department is selected, in the if/else statements. I cant seem too figure out what I'm doing wrong. I've tried different solutions, usually getting different results, the closest being by adding a semi-colon too the last line of the else if statement, which runs the script, skips the first two else statements, and prints the security code.
3 warnings pop up for lines 10, 16, and 22
warning: comparison between pointer and integer [enabled by default]
This is a learning experience for me, and I would appreciate any help that can be offered.
So, the first and most important error is already in the comments, but repeating it here for completeness:
Do not use gets()! It is broken and therefore removed from the current C standard. With gets(), you have no control over how much input is actually read, so any buffer can overflow (and attackers will use that). The replacement is fgets(), which has a size argument.
Note the same holds for things like scanf("%s", ...). If you ever need to use a conversion to a string with the scanf family of functions, make sure to read the documentation, it tells you how to use a field width.
Back to your code, assuming you use fgets() like you should:
char str[20];
fgets(str, 20, stdin);
if (fgets(str, 20, stdin) == 8)
{
You have two errors here:
You call fgets() twice. Each call will attempt to read a line of input and store it in str. That's not what you want.
fgets() doesn't return the length but a pointer to str if it was successfull. If it failed, it returns NULL
So, the code should start like this:
char str[256];
if (!fgets(str, 256, stdin))
{
fputs("Error reading input.", stderr);
return 1;
}
Only after that error check, you should examine the contents of str, ie, what the user actually entered.
Note I also increased buffer size. People might enter longer lines by accident and there's really no need to be that tight with bytes nowadays.
Finally, just checking the length probably isn't a good idea. Instead, include string.h and use the strcmp() function.

using while(!feof) with terminating condition ,still it is going in infinite loop in c

I am coding a program for a library management system as my project in c. I used a while loop along with !feof condition to check the file for book. Since I read that we should not use it, and if we must, we should do it with some break statement and also since I was reading large no. of variables from file, I used found for breaking the while loop. whenever the Target and book.bname will match (using strcmp), found is set to 1 and while loop will be terminated. This is the logic I used behind this code. Here book is a structure of which book.bname is a part. I am using linux os for this program. Please tell me where I am mistaking?
void Searchbook()
{
int i;
char Target[25],stats[3];
int Found=0;
if((librecord=fopen("librecord.txt","r"))==NULL)
printf(" ! The File is Empty...\n\n");
else
{
printf("\nEnter The Name Of Book : ");
scanf("%s",Target);
while(!feof(librecord)&& Found==0)
{
fscanf(librecord,"%d %s %s %d %d",&book.bid,book.bname,book.author,&book.status,&book.nooftitles);
if(strcmp(Target,book.bname)==0)
Found=1;
for(i=0;i<book.nooftitles;i++)
fscanf(librecord,"%s",book.titles);
}
if(Found)
{
if(book.status==IN)
strcpy(stats,"IN");
else
strcpy(stats,"OUT");
printf("\nThe Unique ID of The Book: %d\nThe Name of Book is: %s\nThe Author is: %s\nThe Book Status:%s\n\n",book.bid,book.bname,book.author,stats);
}
else if(!Found)
printf("! There is no such Entry...\n");
fclose(librecord);
}
}
This is a function in which I am facing the infinite loop after entering the name of the book. It goes into an infinite loop printing the name of first book it encounters. What should i do? my problem is different than the other similar question since i am using two conditions instead of only !feof. I am using a variable as a flag .still the while loop is not terminating.
You are not reading the next line from the file as you are not advancing at all.
You need to use fgets to read a string from the file or fgetc to read a char.
fgets stops automatically when it reads a new line character so that could be a solution to read one line at a time.
Another solution if you are using the GNU version of the C library is to use [getLine] (http://man7.org/linux/man-pages/man3/getdelim.3.html) which reads a line for you.
Whatever you use, you need to read a line and then move to the next line until the end is reached, which is not what you are doing with your current code.

How to use fgetc() to capture only letters and storing input to an array

I am trying to write an indexing program where it will take input from the user and store it into an array then keep counting the occurrence of words for example.
user enters: hello##world I,I,I am##!stuck201
hello 1 occurred 1 time
world 1 occurred 1 time
I occurred 3 times
am occurred 1 time
stuck occurred 1 time
So as you can see it will count anything that contains letter(s) separated by anything as a word.
(I am confused on how to go about checking the input for anything other than letters, I was thinking of using ASCII codes but there has to be a better way, if you could just set me in the correct direction for this, Thank you much.)
Before I began the program I was trying to get I/O working and I am having difficulty. The actual program will require me to use 2 dimensional arrays, but if you could help me with this snippet of code that will be appreciated thanks.
#include <stdio.h>
int main()
{
char array[64];
int i=0, j, input;
printf("Please enter an input:");
input==fgetc(stdin);
while(input != " ")
{
array[i]==input;
i++;
input==fgetc(stdin);
}
for(j=0;j<10;j++)
{
printf("You entered:%c",array[j]);
}
}
Upon compilation it gives me a warning "12:14 warning: comparison between pointer and integer"
Output of this code:::
Please enter an input: (I type input) ehehasd world hello (enter)
then it just sits at blank cursor and I have to exit using CTRL C
I want this snippet of code to just take input from user that is separated by a space store it into an array then print out what the user entered. What am I doing wrong?
Check isalpha, it has some fineprints about what it will consider a letter, but it may work for your case.
Another way to do it, if you don't want to do the loop yourself is to use regular expressions. It is fairly easy to make a regex that returns only sequences of letters.
The line (which appears twice in the code):
input==fgetc(stdin);
makes a comparison, not an assignment. Use:
input = fgetc(stdin);
Your line:
while(input != " ")
is incorrect and is the source of the compiler warning. You are comparing a string with a character. You probably intended to use:
while (input != ' ')
and since you could encounter EOF, you probably should use:
while (input != EOF && input != ' ')
You could sensibly use #include <ctype.h> and then:
while (isalpha(input))
which automatically handles EOF (it's a valid input to isalpha(), but returns false; EOF is not an alphabetic character).
Your final loop should probably be:
for (int j = 0; j < i; j++)
(assuming you have a C99 or more recent compiler — if not, declare j outside the loop as now). This only outputs words that have been entered. Otherwise, you'll be printing undefined gibberish.
You'll need to upgrade the code to handle multiple words in the input. At the moment, it stops at the end of the first word (assuming you fix the other problems that I've identified).
Use isAlpha() to test is it is a letter, look here

c - Reading data into an array from file

I have to do a program for class that is using parallel arrays to store data of a students grades. We are to give the arrays data by using the Linux command "<" when executing the program.
./a.out < inputfile
However, when I run the program I get an infinite loop of the menu that program is using to access the data in the arrays. It looks like the program is skipping the function I'm using to populate the arrays from the function and using the data from the file for the menus scanf() that is in a separate function.
Here is the function that I'm using to populate the arrays:
void populate(int idarray[],int testone[], int testtwo[],float hw[],int max)
{
int counter = 0;
while(scanf("%d", &idarray[counter]) != EOF)
{
if(idarray[counter] != -1)
{
//scanf("%f %d %d", &hw[counter], &testone[counter], &testtwo[counter]);
scanf("%f",&hw[counter]);
scanf("%d",&testone[counter]);
scanf("%d",&testtwo[counter]);
counter++;
}
if(counter == max-1)
break;
}
}
"max" is the bounds of the arrays.
the input file would look like:
1983990 75.6 39 78 1935440 50.03 78 34
Check whether your while loop breaks because of counter == max - 1 or by EOF. If it is by the former then you will still be having inputs in stdin which will be given as input to your menu choices without your control
Explanation:
If your while loop breaks because of "counter == max -1" that means your "max"(array size) is lesser
than the total number of inputs(decimal numbers) present in your input file. If your "max"(array size) is appropriate then it will break only by EOF.
Now if the while breaks before reaching EOF, that means you have not consumed all of the input decimal numbers you have passed to stdin, meaning there will be input numbers left to be consumed
even after termination of your while loop. This yet to be consumed inputs will be consumed (in other
words will be given as input to) by your menu choice's "scanf" (which get the choice for the next action). That is the reason for the cursor not waiting for you to give input to your menu choice
You can also forcefully clear your stdin buffer by following the answer( I am not able to flush stdin), just before
calling your menu function, so that it will wait for your input choice
I don't see anything deeply wrong with your function, but your termination criterion appears to be off by one. Off by two, really, if it is tested where you are testing now. Think about what happens when max is 0 or 1.
To accommodate the possibility that max is 0, you need to test the termination condition (correctly) at the very beginning of each loop iteration, before reading anything.
Also, I tend to prefer testing inequalities instead of equalities, as that does a better job of reigning misbehavior when I get my indexing a bit wrong. So in this case I would either break when counter >= max or perform an iteration only when counter < max.

Loop Limit in C/C++

Is there a limit to how many times a loop can run in C?
void main()
{
int T,N,x,X,i;
x=0;
scanf("%d",&T);
while(T>0)
{
T--;
scanf("%d",&N);
X=0;
while(N>0)
{
N--;
scanf("%d",&x);
if(x>X){X=x;}
}
printf("Case: %d",x);
}
}
T has a range of 0-250, and N has a range of 0-1000. x has a range of 0-10,000.
Whenever the N exceeds something above 800, my console stops taking input.
Can this be due to a limit on the input buffer?
There is no limit to how many times a loop may loop. There are limits to the max and minimum values of an int, and those may play into your loop. In this case, 800 should be fine, so there is something else going on here.
Edit: Works for me... the only weird thing I see is that you reset X inside the innermost loop, so the output is always the last integer entered if it's >0, or 0.
Are you piping input to this program? There may be some buffering limitation with that. Try putting the data in a file and read from the file.
It's common practice to loop 10,000 times or (much) more to compare the performance of two small calculations.
If there was a limit, there wouldn't be such as thing as an infinite loop. ;)
Because the comments have gone irreverent on you, I will make this a community wiki and commence with an interrogative-like suggestion that belongs in comments:
Check the return values from all scanf calls. Do this first to determine whether the standard library API is already transmitting information to you -- via "electrostatic transmission", otherwise known as the contents of register eax after you call scanf on x86 architecture. Do not let the light in that register die unobserved. Take the register's electrical charges (bits) into a variable and compare them to both zero (0) and EOF. Those alien transmission were sent to you from the year 1976, when scanf was first written to return an informative numerical value to the caller.
As tomlogic pointed out in comments to an answer, if you are pasting the data, you should instead try using the technique known as "input redirection" or "piping." First, get your data into a file, let's say name filename.dat. Then, issue a command such as the following:
executable-name < filename.dat
Where executable-name is the file you are generating with the C compiler. Technically, the above syntax creates an "input redirection" or "stdin redirection" -- the shell opens the file for read access as file descriptor zero (0), also know as stdin. The child program as spawned from the shell will scanf from the file, rather than the terminal (your paste buffer).
Another approach is to create a "pipe indirection" in which the shell opens another process's output for reading and passes this to the child, again as stdin file descriptor. In this case, the shell probably uses popen rather than open. The syntax for this might be:
cat filename.dat | executable-name as if on a Unix-clone, or
type filename.dat | executable-name if in the context of an IBM® PC-DOS® clone.

Resources