how to make a BufferedReader in C - c

I am really new programming in C. How can I do the same in C, maybe in a more simple way than the one I do in Java?
Each line of the input has two integers: X and Y separated by a space.
12 1
12 3
23 4
9 3
InputStreamReader in = new InputStreamReader(System.in);
BufferedReader buf = new BufferedReader(in);
int n;
int k;
double sol;
String line = "";
line = buf.readLine();
while( line != null && !line.equals("")){
String data [] = line.split(" ");
n = Integer.parseInt(data[0]);
k = Integer.parseInt(data[1]);
calculus (n,k);
line = buf.readLine();
}

Use fgets() to read a line of text and sscanf() to parse it:
#include <stdio.h>
int main(void)
{
int n, k;
char line[64]; // adjust size as necessary
while(fgets(line, sizeof line, stdin) && sscanf(line, "%d %d", &n, &k) == 2)
printf("n=%d, k=%d\n", n, k); // dummy code
return 0;
}
Using scanf() alone to read directly from stdin might be possible with scansets, but it's not as easy as it looks because whitespace characters (including newlines) are skipped.

No compiler, so please fix as needed. Also the variable decalrations are C++ style
#include <stdio.h>
...
while (!feof(stdin)) {
int n = 0, k = 0;
if (scanf("%d %d\n", &n, &k) != 2) continue;
// do something with n and k
}
C++ solution (with streams) may be simpler still

fscanf(filehandle, "%d %d\n", n, k);

The file variable is called FILE
To open a file use fopen()
Reading and writing are done with fgets() and fputs()
This is all in stdio.h.
Example:
#include <stdio.h>
int main(){
FILE *input = fopen("file.txt", "r");
char text[100]; // Where we'll put our text we read
fgets(text, 100, input); // Get up to 100 chars, stops at the first newline
puts(text); // In your example, this should print out "12 1"
fgets(text, 100, input); // Get the next up to 100 chars
puts(text); // Prints "12 3"
return 0;
}
Let me know if there's anything wrong with the code, I don't have a C compiler with me.

Related

scanf is getting skipped, showing segmentation fault [duplicate]

This question already has answers here:
scanf() leaves the newline character in the buffer
(7 answers)
Closed 2 years ago.
This code says segmentation fault cause the program's scanf isn't working. I used a debugger to find out this. The scanf(num) is skipped. And thus the segmentation fault. Can somebody tell why the scanf is being skipped? I used [^\n] so that scanf can read string with spaces. Help.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main(void)
{
int a, b;
scanf("%d %d", &a, &b);
int sumr, maxr;
int sumc, maxc;
int white[b + 1];
white[0] = -1;
int ele[b][a];
for (int opl = 0; opl < a; opl++)
{
for (int pl = 0; pl < b; pl++)
{
ele[pl][opl] = 0;
}
}
char num[100000];
int c = -1;
c:
c++;
scanf("%[^\n]%*c", num);
int hu = 0;
int len = strlen(num);
white[b] = len;
for (int ji = 0; ji < len; ji++)
{
if (isspace(num[ji]))
{
white[hu] = ji;
hu++;
}
}
for (int ft = 0; ft < b; ft++)
{
int lopl = 1;
for (int koi = white[ft + 1] - 1; koi > white[ft]; koi--)
{
ele[ft][c] += lopl * (num[koi] - '0');
lopl = lopl * 10;
}
}
if (a > c)
goto c;
}
scanf("%[^\n]%*c", num);
As a first step. you should always check the return value of functions that can adveresely affect your program. In other words, something like:
if (scanf("%d %d", &a, &b) != 2) { handleOneProblem(); }
if (scanf("%[^\n]%*c", num) < 1) { handleAnother(); }
If that second one fails, then num will be left containing whatever arbitrary data it contained before the call, and you probably don't want to then use it as if it contains a valid string.
On top of that, you should be aware that some, but not all, scanf format specifiers will gobble up white space before attempting to read the data. For example, %d will first skip over whitespace and then attempt to read an integer. However, format specifiers such as [ and c will not.
And none of them will gobble up whitespace after the field has been read for the format specifier. That means, if you want that done, you need to do it yourself, with a set of functions like:
#include <stdio.h>
int gobbleLineFile(FILE *inFile) {
int ch;
while ((ch = fgetc(inFile)) != '\n' && ch != EOF) {}
return ch;
}
int gobbleLineStdIn(void) { return gobbleLineFile(stdin); }
As an aside, a lot of problems with scanf are caused by mixing those format specifiers that skip white-space, with those that don't. You can code around that as per above suggestion but, if you're expecting the user to give line-based input, it's often better to do everything as line-based, then use sscanf to break apart the lines.
A fairly decent line-based input routine can be found here.
You have to catch the '\n' that was left from the first scanf.
Either change it to: scanf("%d %d\n", &a, &b);
or put a getchar(); right after it.
Because the next reading: scanf("%[^\n]%*c", num); will read until the next '\n', which is the first thing left on the buffer.

Reading Rows and Columns from File in C

I am trying to read this input txt file with my C code:
4 3
1.4 4.6 1
1.6 6.65 1
7.8 1.45 0
7 -2 2
and separate them into rows and columns so that I can sort. I tried doing that but I kept getting weird numbers.
So I tried printing out the rows and columns after I read them from the file and the output was zero. I realized then that my code is not reading the numbers from my text file properly. I have tried different means to fix to no avail. Any help or pointers will be highly appreciated.
#include <stdio.h>
#include <string.h>
#include <stdbool.h> //for bool
int main(){
setvbuf(stdout, NULL,_IONBF, 0);
int c;
FILE *file;
FILE *infile;
char filename[99];
char choice;
int rows, columns;
//while(choice == 'y' || choice == 'Y'){
printf("%s", "Enter file name: ");
fgets(filename, 99, stdin);
char *p = strchr(filename, '\n'); // p will point to the newline in filename
if(p) *p = 0;
file = fopen(filename, "r");
if (file) {
while ((c = getc(file)) != EOF)
putchar(c);
fclose(file);
}
else{
puts("FILE NOT FOUND");
}
//read rows and columns from file
printf("%s","\n");
fscanf(file, "%d", &rows);
fscanf(file, "%d", &columns);
printf("%d", rows);
printf("%d", columns);
}
Problem 1
int rows = 0;
int columns = 0;
float matrix[rows][columns];
float sumOfRows[rows];
is not right.
After that, the number of elements in matrix and sumOfRows is fixed. They won't change if you change the values of rows and columns later in your program.
You need to read the values of rows and columns first before you define matrix and sumOfRows.
Problem 2
fscanf(file, "%d", &matrix[rows][columns]);
printf("%f",matrix[rows][columns]);
are not right either. Given the defition of matrix, use of matrix[rows][columns] is not right. They access the array using out of bounds indices.
Remember that given an array of size N, the valid indices are 0 to N-1.
Here's one way to proceed to resolve your problems:
fscanf(file, "%d", &rows); // Use %d, not %f
fscanf(file, "%d", &columns); // Use %d, not %f
// Now define the arrays.
float matrix[rows][columns];
float sumOfRows[rows];
// Read the data of matrix
for (int i = 0; i < rows; ++i )
{
for (int j = 0; j < columns; ++j )
{
fscanf(file, "%f", &matrix[i][j]); // Use %f, not %d
}
}
Your problem (actually, two problems) are in the if (file) {... block. First, you use a loop to read all characters from the file. Because of that, at the end of the loop you are also at the end of the file. Any further calls to fscanf result in undefined behavior.
Second, if the file did not open, you print a message (to the wrong output) and still continue to the fscanf part, which definitely leads to undefined behavior.
Solution: Remove the while loop and fix the error handling code:
if(file) {
// Nothing!
} else {
perror(filename);
return 1; // or return EXIT_FAILURE;
}

How to use fscanf, care about endofline?

I want to read int from a file
The first line is composed of 1 int and the second of 2
ie
1
2 3
if i do
fscanf(FILE, "%d \n %d %d", &a, &b, &c);
I obtain correctly the 3 numbers
but if i put all the numbers on the same line in the file
ie 1 2 3
I obtain the same result (and that's not what i want)
I want to know : How to force the user to go to a new line in his file ?
Edit :
As it seems unclear to some (i'm sorry for that) i want that the file
1
2 3
Produce the result :
a = 1
b = 2
c = 3
And the file
1 2 3
produce either an error or
a = 1
b = 0
c = 0
You need to read each line into a char buffer using fgets and parse each line with its own sscanf. You can use an extra %s on the end of the format string (and an extra pointer argument to a dummy variable of type char *) to detect whether the line contains extra stuff after the fields you're looking for.
fscanf(FILE, "%d", ...); first scans and discard white space before scanning for int characters. In scanning white-space, both ' ' and '\n' are treated the same, so using '%d' loses the end-of-line.
fscanf(FILE, "\n", ...); and fscanf(FILE, " ", ...); do the same thing: scan and discard any white space. Using "\n" does not scan only for '\n'.
Code could use fscanf(FILE, "%d%*1[\n]%d %d", &a, &b, &c) == 3, to find a '\n' after a, but additional '\n' could be lurking in other places.
The only way using scanf() family to detect a '\n' involves using '%c' or '%[]' or '%n'. It is easier to use fgets() and then parse with sscanf() or strtol().
int Read1and2int(FILE *stream, int *a, int *b, int *c) {
char buf[100];
int n;
if (fgets(buf, sizeof buf, stream) == NULL) return EOF;
int count = sscanf(buf,"%d %n", a, &n);
// Non-numeric or extra data
if (count != 1 || buf[n]) return 0;
if (fgets(buf, sizeof buf, stream) == NULL) return 1;
count = sscanf(buf,"%d%d %n", b, c, &n);
// Non-numeric or extra data
if (count != 2 || buf[n]) return 1;
return 3;
}

Which format should I use: scanf \string,string,int,int/?

I have data in the following format \a,b,c,d/ where a,b are strings of letters and numbers; c, d are integers.
I tried using format \%s,%s,%d,%d/ format to scan it, but that causes a,b,c,d/ to be scanf'ed into the first string instead of only a.
Question:
Is there something I could type in the format in order to achieve desired result?
You can use the following format string to use commas as delimiters :
"\\%[^,],%[^,],%d,%d/"
The idea is to tell scanf to read anything that isn't a comma for each string, then read the delimiting comma and continue.
Here is a (bad and unsafe!) example:
char a[100], b[100];
int c=0, d=0;
scanf("\\%[^','],%[^','],%d,%d/", a, b, &c, &d);
printf("%s, %s, %d, %d\n", a, b, c, d);
In real code, you'll want to write something safer. You can for example use fgets to read a full line of input then reuse the same format string with sscanf to parse it.
Read carefully the documentation of fscanf(3).
You might try something like
char str1[80];
char str2[80];
memset (str1, 0, sizeof(str1));
memset (str2, 0, sizeof(str2));
int n3 = 0, n4 = 0;
int pos = -1;
if (scanf ("\\ %79[A-Za-z0-9], %79[A-Za-z0-9], %d, %d /%n",
str1, str2, &n3, &n4, &pos) >= 4
&& pos > 0) {
// be happy with your input
}
else {
// input failure
}
That won't work if you have a wider notion of letters, like French é or Russian Ы ; both are single letters existing in UTF-8 but represented in several bytes.
I added some spaces (mostly for readability) in the format string (but scanf is often skipping spaces anyway, e.g. for %d). If you don't accept spaces -like an input line such as \AB3T, C54x, 234, 65/ , read each line with getline(3) or fgets(3) and parse it manually (perhaps with the help of sscanf and strtol ...). Notice that %d is skipping spaces! I also am clearing the variables to get more deterministic behavior. Notice that %n gives you the amount of read characters (actually, bytes!) and that scanf returns the number of scanned items.
My straightforward solution:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char a[10010];
gets(a);
int l = strlen(a);
char storded_first[10010], storded_second[10010];
char for_int_c[10010], for_int_d[10010];
int c,d;
char first_symbol, last_symbol;
int i;
int cnt = 0;
int j=0;
for(i=0; i<l; i++)
{
if(a[i]=='\\')
first_symbol = a[i];
else if(a[i]=='/')
last_symbol = a[i];
else if(a[i]==',')
{
cnt++;
j=0;
}
else if(cnt==0)
{
storded_first[j]=a[i];
j++;
}
else if(cnt==1)
{
storded_second[j]=a[i];
j++;
}
else if(cnt==2)
{
for_int_c[j]=a[i];
j++;
}
else if(cnt==3)
{
for_int_d[j]=a[i];
j++;
}
}
c = atoi(for_int_c);
d = atoi(for_int_d);
printf("%c%s, %s, %d, %d%c\n",first_symbol, storded_first, storded_second, c, d, last_symbol);
return 0;
}

How to use arbitrary number of scanf() format specifiers?

I want to use infinite type specifiers (%d) in scanf() function.
For example-
printf("Enter numbers: \t");
scanf("--%d SPECIFIERS--");
So its not definite how many nos. the user will enter. I don't want my program to ask the user the 'numbers of characters'.. but I want to allow any the numbers of characters. But its not possible to enter infinite %d in scanf().
So can anyone please tell what is the C program of finding average of numbers given by the user (if you dont know how much nos. the user will give and you don't want the program to ask 'how many numbers.')?
This is tricky. 2 approaches
1 - fgets() Read 1 line, then parse
char buffer[1000];
int count = 0;
double sum = 0;
int num;
fgets(buffer, sizeof buffer, stdin);
const char *p = buffer;
int n;
while (sscanf(p, "%d%n", &num, &n) == 1) {
p += n;
; // do something with `num`
sum += num;
count++;
}
printf("Average %f\n", sum/count);
2 - Lets say you infinite input ends with the end-of-line. Now the problem is that %d will consume all leading whitespace, including \n. Thus we need to consume and test all whitespace beforehand
int count = 0;
double sum = 0;
int num;
for (;;) {
int ws = 0;
while (isspace(ws = fgetc(stdin)) && (ws != '\n'));
if (ws == '\n') break;
ungetc(ws, stdin);
if (scanf("%d", &num) != 1) break;
; // do something with num
sum += num;
count++;
}
printf("Average %f\n", sum/count);
If you really interested in infinite number of inputs the just try this
while(1)
{
printf("Enter numbers: \t");
scanf("%d", number);
}
It will take input until you forcibly close your program!
But does it make any sense of doing this ?
You should have some way of knowing where the input ends. There are many ways for it and each has a possibly different solution. The two most common ones would be:
Input finishes at end-of-line
The solution is to read one line and then parse the line to get your numbers until the line ends.
This has the benefit that the program could ask for other input afterwards for other parts of the program. The disadvantage is that the user has to input all the numbers in the same line.
Input finishes at end-of-file
Simply loop, reading one number until end of file:
while (scanf("%d", &num) == 1)
/* do something with num */
Note: the user can enter end-of-file in a Linux console with Ctrl+D
If the user input is always numbers separeted by spaces and then at the end is an enter (newline). Then you can use the following code
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int input;
char c;
while (scanf(" %d%c", &input, &c) == 2 ) {
printf("number is %d\n", input);
if ( c == '\n') break;
}
}
If the use want to communicate the number of input as argument
int main(int argc, char *argv[])
{
int number_of_input = atoi(argv[1]);
int input, i;
for (i=0; i<number_of_input; i++) {
scanf(" %d", &input);
}
}
and when you call you program. you call it in this way:
$ myprogram 5
and 5 here is the number of the integer that you can input
myprogram will be saved in argv[0]
5 will be saved in argv[1]
myprogram and 5 are saved as sting in the argv[] array. atoi(argv[1]) will convert the "5" as string to 5 as integer
you can make the user enter an infinite integer input in this way too:
int main(int argc, char *argv[])
{
int input, i;
while (1) {
scanf(" %d", &input);
}
}
And you can give the user a way to stop this infinite loop:
int main(int argc, char *argv[])
{
int input;
while (scanf(" %d", &input) != EOF) {
//....
}
}
here you can stop the infinite loop with
EOF = CTRL + D (for Linux)
EOF = CTRL + Z (for Windows)
At first reading, the solution to a problem like this is to loop until the user inputs a "done" character. This could be a letter Q for example. By reading in the input as a string you can process both numbers and letters. The code below processes one input at a time (followed by ) - with the possibility to either Quit (terminate program), or Clear (restart calculation, keep program running):
printf("Enter numbers to average. Type Q to quit, or C to clear calculation.\n");
char buf[256];
double sum=0, temp;
int ii = 0;
while(1)
{
printf("Input: \t");
fgets(buf, 255, stdin);
if (tolower(buf[0])=='q') break;
// allow user to "clear" input and start again:
if (tolower(buf[0])=='c') {
sum = 0;
ii = 0;
printf("Calculation cleared; ready for new input\n");
continue;
}
ii++;
sscanf(buf, "%lf", &temp);
sum += temp;
printf("At this point the average is %lf\n", sum / (double)ii);
}
printf("Done. The final average of the %d numbers is %lf\n", ii, sum / ii);
EDIT Following some back-and-forth in the comments to this and other answers, here is a solution that addresses your problem. Code has been tested - it compiles, runs, gives expected results:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void){
double sum=0;
int ii=0;
char buf[256], *temp;
char *token;
printf("Enter the numbers to average on a single line, separated by space, then press <ENTER>\n");
fgets(buf, 255, stdin);
temp = buf;
while((token=strtok(temp, " ")) != NULL) {
temp = NULL; // after the first call to strtok, want to call it with first argument = NULL
sum += atof(token);
ii++;
printf("Next token read is number %d: '%s'\n", ii, token); // so you see what is going on
// remove in final code!!
}
printf("AVERAGE: ***** %lf *****\n", sum / (double)ii);
return 0;
}
One more edit If you want to use getline instead (which you asked about in the comments - and it's even safer than fgets since it will increase the buffer size as needed), you would change to change the code a little bit. I am just giving some of the pertinent lines - you can figure out the rest, I'm sure:
double sum=0;
char *buf, *temp; // declaring buf as a pointer, not an array
int nBytes = 256; // need size in a variable so we can pass pointer to getline()
buf = malloc(nBytes); // "suggested" size of buffer
printf("Enter numbers to average on a single line, separated with spaces\n")
if (getline(&buf, &nBytes, stdin) > 0) {
temp = buf;
// rest of code as before
}
else {
// error reading from input: warn user
}
I am sure you can figure it out from here...

Resources