c - Reading data into an array from file - c

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.

Related

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

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.

Why does getch() output 10 characters on first run (line) but 9 characters for all following lines?

I have this program that create a new line after every 10 characters. However, once it hits the second iteration and there after it only outputs 9 characters. The program works if I set the second i to -1 but I do not understand why it will not work with i set to 0. The logic is the exact same as the first run as the first i is only run once, so when I want a new line I reset i. Can someone explain what I am missing? I drew out the steps on paper but it still doesn't make sense. Thank you.
#include <stdio.h>
#include <ncurses.h>
#define MAXLINE 10
// count number of chars, once it reaches certain amount
int main (void)
{
//cbreak();
// to open curses terminal
initscr();
int i, c;
// first iteration set to 1
for (i = 0; (c = getch()) != EOF; i++)
{
if (i == (MAXLINE-1))
{
printf("\r\n");
i = 0; // Counter is reset. To break out of the loop use CTRL + D.
}
}
// to close curses terminal
endwin();
}
The first time through the loop i is zero. When you set i to zero inside the loop, when control reaches the end of the for, the statement executed is i++ (making i 1), then (c = getch()) != EOF
The first iteration starts with i set to zero. When the test in the loop resets i to zero, the usual execution of i++ in the for loop still occurs, so the next iteration has i set to one, not zero.
You seem to intermixed both of my examples of my previous answer to your previous question.
Unfortunately, It seems that I didn´t pointed out the reset explicitly although I hinted the difference. I apologize.
The reset needs to be 1 less than the initial start value of the counter because the counter gets incremented at the end of the loop in which the reset takes place, although the incrementation should be only valid for every fully next iteration. We need to make it one integral value less to compensate this effect.
In your actual code, You need to replace i = 0; with i = -1 as seen in one of the examples in my previous answer.
Furthermore, the commenting of cbreak() isn´t a good idea as the console can be either in cbreak() or nocbreak() mode when the program is started up (it is not fixed). Use the explicit cbreak() to determine that the input will immediately read by characters, without the wait for a newline character to flush the buffer.
The Linux man page says:
"Initially the terminal may or may not be in cbreak mode, as the mode is inherited; therefore, a program should call cbreak or nocbreak explicitly."

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

Please Explain this Example C Code

This code comes from K&R. I have read it several times, but it still seems to escape my grasp.
#define BUFSIZE 100
char buf[BUFSIZE];
int bufp = 0;
int getch(void)
{
return(bufp>0)?buf[--bufp]:getchar();
}
int ungetch(int c)
{
if(bufp>=BUFSIZE)
printf("too many characters");
else buf[bufp++]=c;
}
The purpose of these two functions, so K&R says, is to prevent a program from reading too much input. i.e. without this code a function might not be able to determine it has read enough data without first reading too much. But I don't understand how it works.
For example, consider getch().
As far as I can see this is the steps it takes:
check if bufp is greater than 0.
if so then return the char value of buf[--bufp].
else return getchar().
I would like to ask a more specific question, but I literally dont know how this code achieves what it is intended to achieve, so my question is: What is (a) the purpose and (b) the reasoning of this code?
Thanks in advance.
NOTE: For any K&R fans, this code can be found on page 79 (depending on your edition, I suppose)
(a) The purpose of this code is to be able to read a character and then "un-read" it if it turns out you accidentally read a character too many (with a max. of 100 characters to be "un-read"). This is useful in parsers with lookahead.
(b) getch reads from buf if it has contents, indicated by bufp>0. If buf is empty, it calls getchar. Note that it uses buf as a stack: it reads it from right-to-left.
ungetch pushes a character onto the stack buf after doing a check to see if the stack isn't full.
The code is not really for "reading too much input", instead is it so you can put back characters already read.
For example, you read one character with getch, see if it is a letter, put it back with ungetch and read all letters in a loop. This is a way of predicting what the next character will be.
This block of code is intended for use by programs that make decisions based on what they read from the stream. Sometimes such programs need to look at a few character from the stream without actually consuming the input. For example, if your input looks like abcde12xy789 and you must split it into abcde, 12, xy, 789 (i.e. separate groups of consecutive letters from groups of consecutive digits) you do not know that you have reached the end of a group of letters until you see a digit. However, you do not want to consume that digit at the time you see it: all you need is to know that the group of letters is ending; you need a way to "put back" that digit. An ungetch comes in handy in this situation: once you see a digit after a group of letters, you put the digit back by calling ungetch. Your next iteration will pick that digit back up through the same getch mechanism, sparing you the need to preserve the character that you read but did not consume.
1. The other idea also shown here can be also called as a very primitive I/O stack mangement system and gives the implementation of the function getch() and ungetch().
2. To go a step further , suppose you want to design an Operating System , how can you handle the memory which stores all the keystrokes?
This is solved by the above code snippet.An extension of this concept is used in file handling , especially in editing files .In that case instead of using getchar() which is used to take input from Standard input , a file is used as a source of input.
I have a problem with code given in question. Using buffer (in form of stack) in this code is not correct as when getting more than one extra inputs and pushing into stack will have undesired effect in latter processing (getting input from buffer).
This is because when latter processing (getting input) going on ,this buffer (stack) will give extra input in reverse order (means last extra input given first).
Because of LIFO (Last in first out ) property of stack , the buffer in this code must be quene as it will work better in case of more than one extra input.
This mistake in code confused me and finally this buffer must be quene as shown below.
#define BUFSIZE 100
char buf[BUFSIZE];
int bufr = 0;
int buff = 0;
int getch(void)
{
if (bufr ==BUFSIZE)
bufr=0;
return(bufr>=0)?buf[bufr++]:getchar();
}
int ungetch(int c)
{
if(buff>=BUFSIZE && bufr == 0)
printf("too many characters");
else if(buff ==BUFSIZE)
buff=0;
if(buff<=BUFSIZE)
buf[buff++]=c;
}

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