How to skip reading something in fscanf - c

If I have the following text file:
1 2 3 4 5 6 7 8 9 10 YEAH
11 12 13 14 15 16 17 18 19 20 YEAH
I have to following code:
#include <stdio.h>
int main(){
int arr[5][10];
FILE* foo;
foo = fopen("help.txt", "r");
int i, j;
int temp;
while (i<5 && (fscanf(foo, "%d", &temp)) !=EOF ){
arr[i][0]= temp;
for (j=1; j<10; j++){
fscanf(foo, "%d", &temp);
arr[i][j]=temp;
}
i++;
}
for (i=0; i<2; i++){
for (j=0; j<10; j++)
printf("%d ", arr[i][j]);
printf("\n");
}
fclose(foo);
}
...and it works perfectly fine when the text file has just numbers but when I add the characters "Yeah" to the text file, the code goes crazy. How do I include them? Please explain simply as I am still very new to this. Would I used fscanf(foo, %d%*c, &temp);??? Also how would I handle the new line statement if there is one?
Thank you very much
Edit:
the e input I provided initially was
1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20.
Here everything is printed out correctly. When adding the word yeah to the text file after 10 the all the other numbers are 10 as well. Essentially it does not contain 11 12... to 20. and prints out: 1 2 3 4 5 6 7 8 9 10
10 10 10 10 10 10 10 10 10 10

It is always easier to process data like this one line at a time, rather than one "token" at a time directly against the file.
Reading in a whole line with fgets() into a suitably big buffer, gives you the opportunity to take your time and go back and forth in the parsing, since it's all just bytes in memory at that point and you no longer risk confusion due to the file having a current position which is incremented as you read.
Your example conversion doesn't work, since you need something like "n numbers followed by something that is not a number, then end of line" which I don't think can be expressed as a single simple fscanf() conversion string.
Much easier to read in the whole line, then look at it token by token "by hand". See, for instance strtok() which is kind of dangerous in general but should be fine here.

Try this:
int e;
while (i<5 && (e = fscanf(foo, "%d", &temp)) !=EOF ){
if(e==0) {
fscanf(foo, "%*[^0-9]"); // this will skip the non numeric chars
continue;
}
arr[i][0]= temp;
and
for (j=1; j<10; j++){
e = fscanf(foo, "%d", &temp);
if (e==EOF) break;
else if (e==0) {
fscanf(foo, "%*[^0-9]"); continue;
}
arr[i][j]=temp;

Related

How to scan and print an array with a max of 20 variables?

In C, how do I scan an print an array of 20 numbers given by the user.
Example desired output:
Enter data: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
The data entered is: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
This is what I have so far for my loop:
for (i = 0; i <= 20; i++){
scanf("%d", &arry[i]);
}
This however keeps asking for 21 inputs before the loop terminates.
Everything is fine except that =. It means:
Run FOR-LOOP from 0 up to 20.
Which means a total of 21 values. Just remove that = and you are good to go:
for (i = 0; i < 20; i++)
{
scanf("%d", &arry[i]);
}
for (i = 0; i < 20; i++){
scanf("%d", &arry[i]);
}
We should always remember that when we are declaring an array of size n, then an array of n elements with indexes 0 to n-1 is allocated. We should not access to those memory locations which are not allocated to us , The C does not allow you to do so,your program may crash.Though your compiler may not give any error message.
It is a good practice to do this.

Using Multiples in C

I'm trying to teach myself C and have only done a few things in CodeAcademy so far. I'm pretty lacking when it comes to loops in my current online course. Let's say I wanted to use a loop to make the first 5 multiples of 1 through 10 like below.
Number 1st 2nd 3rd 4th 5th
1 1 2 3 4 5
2 2 4 6 8 10
3 3 6 9 12 15
4 4 8 12 16 20
5 5 10 15 20 25
6 6 12 18 24 30
7 7 14 21 28 35
8 8 16 24 32 40
9 9 18 27 36 45
10 10 20 30 40 50
I'm drawing a blank on how I would use loop nesting or even a single loop to do the above. Anyone have any advice on where to start, I'm not understanding this I guess.
A big part of programming is about breaking larger problems into smaller problems.
If the problem of making this table is too much for you, then break the problem into pieces. e.g.
Write a function that can print the header
Write a function capable of printing one line of the table
Write a program that uses those two functions to print the whole table
see printf description
#include <stdio.h>
int main(void){
char *field_name[] = {"Number", "1st", "2nd", "3rd", "4th", "5th" };
int field_size = 10;
int num_of_fields = 6;
int number_max = 10;
//print field_name
for(int i = 0; i < num_of_fields; ++i)
printf("%-*s", field_size, field_name[i]);
puts("");
//print numbers
for(int n = 1; n <= number_max; ++n){
printf("%-*d", field_size, n);
for(int i = 1; i < num_of_fields; ++i)
printf("%-*d", field_size, n * i);
puts("");
}
return 0;
}

C What is up with my Matrix Reader?

so I am trying to make a matrix reader that will take a text file that contains only data for a NxN matrix such as:
10 9 8 7
6 5 4 3
2 1 0 1
Read the test file into a dynamic multidimensional array. The program will not have headers, so it will need to read the entire file in order to obtain # of rows/cols.
Once I have all the data in my array I then will be able to manipulate how I want (i.e. swapping columns/rows, reversing order, etc).
At this point I am just trying to get my program to simply output the array as it appears in the test file once the entire matrix has been read in.
Here is what I have written so far:
#include <stdio.h>
#include <stdlib.h>
int main() {
int n;
int i=0;
int j=0;
scanf("%d", &n);
int **array;
array = malloc(n * sizeof(int *));
if(array == NULL) {
printf("Out of memory\n");
exit(1);
}
for(i = 0; i < n; i++) {
array[i] = malloc(n * sizeof(int));
if(array[i] == NULL) {
printf("Out of memory\n");
exit(1);
}
}
for(i = 0; i < n; i++) {
for(j = 0; j < n; j++) {
int k;
scanf("%d", &k);
array[i][j] = k;
printf("%d ", array[i][j]);
}
}
}
And running this gives me output:
9 8 7 6 5 4 3 2 1 0 1 1 1 1 1 1 1 1 1 1 1 1... repeating 1's...
I am not sure what is wrong with my code I have been staring at it for a solid hour and have made 0 progress.
Because my output prints out about 100 different ints I feel that my problem lies in my printing loops, and I feel like it has something to do with int n, but I am not sure how to deal with this.
Any help with be greatly appreciated! Thanks.
The issue is as follows: The first number that is obtained from your file is 10 and that is being stored inside the int n close towards the beginning. That value defines the width and height of your multi-dimensional array, your matrix. You then ask for further values from that file, exactly 10 * 10 many times.
The file, however, only has 4 * 3 - 1 = 11 numbers left in it. It provides them all, right into the int k. Those values get stored inside your matrix, printed. After the 11th (or 12th if you count the first 10) the scanf starts failing. As it fails, it returns the value EOF == -1 but you do not recognize that.
Failure leaves the k as it is, although I am not sure whether it is guaranteed to remain what it previously was, since as far as I know, k could very well have another memory location allocated for itself with each cycle, since (again) as far as I know it gets cleared at the end of each loop. In your case, it does keep its value, luckily I would say, and that gets stored/printed.
In the end, you should have exactly 100 numbers printed, because of that 10 at the very beginning.
Even if you had an additional 4 at the very beginning, you'd end up with a matrix that has a wild last line with all 1s.
If you want to have a 3 by 4 matrix in your hands, consider making your file as the following example:
3 4
10 9 8 7
6 5 4 3
2 1 0 1
Then read the first value into an int n and then second one into an int m. Make first memory allocation with malloc( n * sizeof * array );, then the secondary allocations with malloc( m * sizeof ** array );.
You could also alternatively omit reading anything, deduce how many rows and columns your matrix should have by reading the amount of new-line '\n' occurrences in your file (plus one), as well as amount of numbers there are on a single line.
Edit:
Okay, let's show this you could also part: This is just an example, I'll be using a pair of scanfs for counting both the amount of lines that have at least one number inside and amount of numbers on a single line.
...
int n = 0;
int m = 0;
int discardable;
while ( scanf( "%d", &discardable ) == 1 ) {
// as long as a number has been successfully read
n++;
if ( scanf( "%*[^\n]" ) != 0 )
// discard everything until a '\n'
// and if you fail to encounter a '\n' anywhere until the file ends...
break;
}
// rewind back to the beginning of the file
rewind ( stdin );
while ( scanf( "%d", &discardable ) == 1 ) {
// as long as a number has been successfully read
m++;
if ( scanf( "%*[ \t]" ) != 0 || stdin->_ptr[0] == '\n' )
// discard every ' ' or '\t'
// if you rather get carried until the end of file, break
// else, if the upcoming character is '\n', again, break
break;
}
rewind ( stdin );
...
There you have it, n and m here should be storing the height and width of the matrix you should have, respectively.
This is just a way to do it, I can see why many could potentially just hate this, because I have made use of the FILE structure, and referred to _ptr, but whatever. I personally would prefer this any day over carrying a temporary character array and read from it.

How to read a graph from console without knowing how many edges it has? [duplicate]

This question already has answers here:
How to read the standard input into string variable until EOF in C?
(5 answers)
Closed 9 years ago.
I have this graph (with the first line is number of vertices, the following lines are directed edges):
9
1 4
1 5
2 5
4 5
4 6
6 9
7 6
7 8
8 9
There is no information to know how many edges are in the input so can anyone suggest a way to read this kind of input?
Thank you you all,
I finally solved it, here is the input code:
while (1) {
tmp1 = scanf("%d", &x);
if (tmp1 == -1) // fix here
break;
tmp2 = scanf("%d", &y);
new_vertex = (Vertex *) malloc(sizeof(Vertex));
new_vertex->adj_vertex = NULL;
new_vertex->vertex_no = y;
new_vertex->time_stamp_visit = 0;
new_vertex->time_stamp_finish = 0;
last_vertex = getLastVertex((graph+x));
last_vertex->adj_vertex = new_vertex;
}
Loop over this list from 1 to n-1 read the pair and insert the edge between these two nodes in your graph data structure.
I advise reading this: http://shygypsy.com/iotutorial.html
And using the method under "Read integers, one at a time, skipping whitespace, until the end of input."
In your code maintain state on whether it's a beginning or a ending vertice being inputted.
Don't forget to press ctrl+d when done typing input.
You can use a "termination character" that counts as EOF, like a -1 or something after the last pair of nodes.
Then your data would be:
9
1 4
1 5
2 5
4 5
4 6
6 9
7 6
7 8
8 9
-1
And your code:
while(1){
scanf("%d %d", &num1, &num2);
if(num1==-1) break;
// process
}
I wrote getnum() to return an integer from stdin:
int getnum(int * last) {
int c, n = 0;
while ((c = getchar()) != EOF && 0x30 <= c && c < 0x40)
n = n * 10 + (c - 0x30);
if (last)
*last = c;
return n;
}
It will get digits from stdin until a non-digit character is retrieved. Because getnum() doesn't care what the non-digit character is, it doesn't matter how the numbers are arranged. They could all be on the same line, or in space-delimited pairs, one per line. I put this in a loop that stops once it reads in the right number of numbers, but you could easily loop until last pointed to non-whitespace.
Additionally, if you want to read from a FILE or fd (integer file descriptor), pass the FILE/fd to getnum() and use getc(FILE *)/fgetc(int).

Error reading test cases from a file in C

for a programming homework, I'm implementing Prim's algorithm, the format of the input file for test cases is as follows:
The first line of input will be an integer C, which indicates the number of test cases. The first line of each test case contains two integers N and E, where N represents the number of nodes in the graph and E the number of edges, respectively. Then come E lines, each with 3 integers I, J and P, where I and J represent the nodes of an edge (undirected graphs, where 0 ≤ I, J
Although even I'm starting the code (I'm new to programming) i Don´t understand why my code only reads an entry for the test cases, What am I doing wrong?
this is the code reading the file entradaA.in:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (int argc, char *argv []){
int testCases;
int numberNodes;
int numberEdges;
freopen("entradaA.in", "r", stdin);
int i, j, cont=1;
int total = 0;
int a, b, c;
scanf ("%d", &testCases);
for (i=0; i<testCases; ++i)
{
scanf ("%d %d", &numberNodes, &numberEdges); //Number Nodes & Edges
for (i=0; i<numberEdges; i++)
{
scanf ("%d %d %d", &a,&b,&c);//
printf ("%d %d %d\n", a, b, c);
}
printf ("Caso %d: Total Weight %d\n", cont++, total);
}
return (0);
}
The input file (entradaA.in) look something like this
2
7 11
0 1 17
0 2 10
0 6 14
1 2 6
1 3 1
2 3 4
2 6 3
3 4 7
4 6 10
4 5 2
5 6 9
6 9
0 1 30
0 2 30
1 3 22
1 5 33
2 3 20
2 4 33
3 4 15
3 5 20
5 4 20
You have the loop variable i modified inside the loop, which is generally unwanted. In this case, since i looped to 11 (the number of edges), it caused your program to terminate since 11 is not smaller than 2 (the number of test cases in the input).
You could use temporary variable (if you are using C++, thank you aardvarkk):
for (int i=0; i<testCases; ++i)
{
scanf ("%d %d", &numberNodes, &numberEdges); //Number Nodes & Edges
for (int j=0; j<numberEdges; j++)
Note that the int j could also be int i, but I wouldn't recommend it. Just use a variable with another name would be clearer. Or if you are in C, just drop the two int and use variables that are local to the function.
For more, you could read this.
Your code produced the following output on my machine. The only change I made was to declare the int values i, j etc. before the freopen call to make the code standard C.
0 1 17
0 2 10
0 6 14
1 2 6
1 3 1
2 3 4
2 6 3
3 4 7
4 6 10
4 5 2
5 6 9
Caso 1: Total Weight 0
It's definitely reading more than your test cases, so I'm not sure what the problem is?

Resources