I need to read an input file like :
1
19 20 41 23
2
41 52 43
3
90 91 941
4
512
5
6
51 61
Each odd line is an integer. Each even line is unknown number of integers.
It is very easy in C++
while( cin >> k ){
............
}
I'm not so used to C, so I couldnt make it in C. Any ways to do it?
Running your input file through:
#include <stdio.h>
int main() {
int k;
while (scanf("%d", &k) == 1) {
printf("read number: %d\n", k);
}
return 0;
}
Results in:
read number: 1
read number: 19
read number: 20
read number: 41
read number: 23
read number: 2
read number: 41
read number: 52
read number: 43
read number: 3
read number: 90
read number: 91
read number: 941
read number: 4
read number: 512
read number: 5
read number: 6
read number: 51
read number: 61
This is the C analog of the code you reference in your original question.
The way I would do it is to break it down into two operations: read a line, then read the integers in that line. Here is a lazy implementation using the standard C library:
char line[1024], *p, *e;
long v;
while (fgets(line, sizeof(line), stdin)) {
p = line;
for (p = line; ; p = e) {
v = strtol(p, &e, 10);
if (p == e)
break;
// process v here
}
}
I would break the program in different tasks.
The first step is to be able to read a pair of lines, the first line which tells you the number of numbers to read, and then the second line to read the actual numbers. For this, a function called something like read_set might be useful. It should be able to return the numbers read, and signal end of file as well as errors. For this, we can define a data structure such as:
struct numbers {
long *data; /* or choose a type depending upon your needs */
size_t len;
};
and then we can declare our function with the prototype:
int read_set(FILE *fp, struct numbers *num);
The function will allocate memory for num->data, and set num->len to the correct value. It returns 0 for success, and a set of error conditions otherwise. We might get fancy and use an enum for return statuses later. For now, let's say that 0 = success, 1 = end of file, and everything else is an error.
The caller then calls read_set() in a loop:
struct numbers numbers;
int status;
while ((status = read_set(fp, &numbers)) == 0) {
/* process numbers->data, and then free it */
}
if (status == 1) {
/* hit end of file, everything is OK */
} else {
/* handle error */
}
For implementing read_set(): it has to read two lines. There are many implementations of reading a full line in C, so you can use any of them, and read a line first, then sscanf()/strtoul() it for one number (check its return value!). Once you have the number of numbers, n, you can read the next line in memory, and do:
num->data = malloc(n * sizeof *num->data);
num->len = n;
You can then repeatedly call sscanf() or strtol() to store numbers in num->data. You should put in checks to make sure exactly n numbers are on that line.
Note that you can write read_set() in other ways too: read a line character by character, and parse the numbers as you read them. This has the advantage of going over the data only once, and not needing a big buffer to store the whole input line in memory, but the disadvantage is doing low-level stuff yourself and reading data character-by-character may be slow.
I would do one of:
fgetc() to read individual characters and parse them yourself (accumulate digits until you hit whitespace and you have an integer to convert with atoi(); if the whitespace is a newline, then it terminates a list of integers)
fgets() to read a line at a time, and then parse the string (again, look for whitespace separating the values) that it returns.
I came up with a solution like this:
#include <stdio.h>
int main(void)
{
int index = 0;
char ch;
int arr[1024];
while(scanf("%d%c", &arr[index++], &ch)!=EOF)
{
if(ch=='\n')
{
// One line is read into arr
// number of integers in this line = index
// Rest of your code which can proces arr[]
// Example
int i;
for(i = 0; i < index; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
// Set the index back to 0 for the upcoming line
index = 0;
}
}
return 0;
}
have a look at getc(3) or scanf(3)
Related
I'm very new to programming and C. I have textfile with some random text and an integer that i want to find and save. The textfile looks something like this (I only want to save 23 in this case, not 56):
# this is a comment
23
this is some random text
56
And this is the code I have:
int *num = malloc(sizeof(int));
*num = fgetc(f);
while(!feof(f)){
*num = fgetc(f);
if(isdigit(*num)){
break;
}
}
if(!isdigit(*num)){
printf("Error: no number found.\n");
free(num);
}
else{
printf("%c\n", *num);
}
I'm kinda stuck right now and my program only prints out the number 2 :/
Very thankful for help.
As #pbn said you're better off using sscanf.
But if you really, really want, you can do it your way, by reading one character at a time, but you'll need to "build" the integer yourself, converting the character to integer, keeping track of what you have, and multiplying by powers of 10 for every digit the number that you already have.
Something like this (not complete code, it's just to get you started):
int c;
int num = 0;
while (c = fgetc(f)) {
if(!isdigit(c)) {
break;
}
num = (num * 10) + (c - '0');
}
The c- '0' part is to convert the text representation of the integer to the integer itself. 0 is character 48, 1 is 49 and so on.
This is assuming that on the line with numbers, you ONLY have numbers, not a mix of numerical and non-numerical characters.
Also, do not use !feof(file).
One option could be using getline and sscanf functions. I assumed that text lines do not contain numbers:
#include <stdio.h>
int main() {
int value, matched = 0;
char *line = NULL;
size_t size;
while(getline(&line, &size, stdin) != -1) {
if ((matched = sscanf(line, "%d", &value)) != 0)
break;
}
if (matched)
printf("value: %d\n", value);
return 0;
}
This part:
while(getline(&line, &size, stdin) != -1) {
will try to read the entire stream line by line.
Next line uses sscanf return value, which is the number of input items successfully matched and assigned, to determine whether the integer value has been found. If so it stops reading the stream.
One simple way in your program is once you find digit don't just stop continue untill you find next " " , "\n" , "\0" . Till then add Number = Number*10 +(*num);, define Number as global or something.
I'd like to read all integers from a file into the one list/array. All numbers are separated by space (one or more) or end line character (one or more). What is the most efficient and/or elegant way of doing this? Functions from c++ library are prohibited.
I did it this way:
/* We assume that 'buffer' is big enaugh */
int i = 0;
while(fscanf(fp, "%d", &buffer[i]) != EOF) {
++i;
}
Sample data:
1 2 3
4 56
789
9 91 56
10
11
OP's code is close. Test against 1 rather than EOF so code does not get caught in a endless loop should non-numeric data occur. I'd use a for() loop, but while is OK too.
Note that "%d" directs fscanf() to first scan and discard any white-space including ' ' and '\n' before looking for sign and digits.
#define N 100
int buffer[N];
int i,j;
for (i=0; i<N; i++) {
if (fscanf(fp, "%d", &buffer[i]) != 1) {
break;
}
}
for (j=0; j<i; j++) {
printf("buffer[%d] --> %d\n", j, buffer[j]);
}
You can use fgets to read each line from the file into a string, say char *line .
Then you can loop through that string char by char and use isDigit to determine if the character is a digit or not.
To read numbers with more than one digit place each digit in a string and use atoi to convert them to an integer
I have the following code snipped to read 16 unsigned char values from a .txt file.
#include<stdio.h>
#include<stdlib.h>
int main()
{
int i, j, k, load_size;
unsigned char *buf;
load_size = 16;
buf = (unsigned char *)malloc(load_size);
FILE *fin;
fin = fopen("demo_input1.txt", "r");
fread(buf, 1, load_size, fin);
for(i=0;i<16;i++){
printf("%d ", *buf);
buf++;
}
system("PAUSE");
}
The file 'demo_input1.txt' contains the values 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16. But I am getting output in the console values 49 32 50 32 51 32 52 32 53 32 54 32 55 32 56 32. Can anybody help me by telling me what is going wrong here? Thanks
fread is for reading raw inputs. As your file is formatted text, use the following:
int nums[SIZE];
int count = 0;
while( fscanf(fin, "%d", nums + count) == 1 ) {
if(++count == SIZE) break; /* More than expected numbers in file */
}
Later you can print using:
for(i = 0; i < count; i++) {
printf("%d ", nums[i]);
}
fscanf is one way to read formatted input from files. You can use malloc, walking pointers as shown in your original code snippet or as per your requirements.
What is going on is completly correct, yet not what you expected. So, whats going on? You read 1 byte from the file, into a char, then you output it using %d, which will output as decimal. Have a look at an ascii table, if you read the char 1, its ASCII value is 49, 32 is space, 50 is 2, and so on. You cannot just read plain numbers like that, your code, replacing the %d with %c would only work on binary files, but not on human readable files.
What you want to use instead of fread is fscanf, which works like scanf but reads from a file. There you can specify to read an integer, thus getting the whole numbers without the spaces. These you can check if they are smaller than 256, if yes, cast to char.
The other way of how this can be done is using fgets() to read the whole line to the buffer break the line using space as delimiter and later convert string to integers and store them or print them.
char buf[300];
int a[30],i=0;
while(fgets(buf,sizeof(buf),fin))
{
char *p = strtok(buf," ");
i = 0;
while( p != NULL)
{
a[i] = atoi(p);
printf("%d ",a[i]);
i++;
p = strtok(NULL," ");
}
}
PS: When fgets() is used you need to have predefined large array to hold your input else it may lead to erroneous results.
It is considering the ascii value of space as 32(ASCII for space).
Just make one simple change in the for loop.
Instead of %d use %c
for(i=0;i<16;i++)
{
printf("%c ", *buf);
buf++;
}
Here is a solution to a CODECHEF Problem "INTEST", which basically tests how fast IO operation is done by a code.
Input
The input begins with two positive integers n k (n, k<=107). The next n lines of input contain one positive integer ti, not greater than 109, each.
Output
Write a single integer to output, denoting how many integers ti are divisible by k.
The following code segment is the fastest C Code submitted so far:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 65535
int main(int argc, char *argv[])
{
char buffer[SIZE];
unsigned long n, k, input, count;
int c, i;
count = 0;
scanf("%lu %lu\n", &n, &k);
input = 0;
while ((c = fread (buffer, sizeof (char), SIZE, stdin)) > 0)
{
for (i = 0; i < c; i++)
{
if (buffer[i] == '\n')
{
//printf("%d\n", input);
if ((input % k) == 0)
{
count++;
}
input = 0;
}
else
{
input = (input * 10) + (buffer[i] - '0');
}
}
}
printf("%lu\n", count);
return 0;
}
They said that fread() offers a faster IO than scanf as fread() does a buffer IO. But when I compile and run it on my own computer(CODEBLOCKS) and give it a few inputs from the console[Note: I am not piping the input file], suppose I enter 4 3 on the first line denoting that 4 more lines follow. But fread() is not even bothering to accept the 4 more lines and after taking one more input basically the program outputs a 0 if I enter a number divisible by 3 or 1 if the number enter is not divisible by 3 and just terminates.
Why is fread() terminating before accepting all the inputs?
In case of file IO, we can be sure that fread() will read until buffer is full or a file terminator is encountered. But in case of stdin, how long will fread() wait for the user to enter inputs?
Why the program is using a buffer of SIZE 65536?
When the input comes from a terminal, the terminal driver hands data over after each line, and fread() only returns what's available. After the scanf(), the first call to fread() will likely return just one byte, the newline left behind by scanf(). Thereafter, each call will read a single line, because that's the way the terminal driver works.
By contrast, if the input is a regular file, then the fread() call will return as many characters as are available, up to the size of the buffer, completely ignoring newlines as special cases.
If the input is a pipe, then it will read what is available in the pipe at any given time, which might or might not be multiple lines of data, depending on how it is written and whether the reading code keeps up with the writing code.
#include<stdio.h>
int main(){
int i,n,k,m[50],count;
printf(" ");
scanf("%d %d",&n,&k);
count=0;
for(i = 1; i <= n; i++){
printf(" \n");
scanf("%d",&m[i]);
if(m[i] % k==0){
count=count + 1;
}
}
printf("ans=%d",count);
return 0;
}`enter code here`
These are the directions:
Read characters from standard input until EOF (the end-of-file mark) is read. Do not prompt the user to enter text - just read data as soon as the program starts.
Keep a running count of each different character encountered in the input, and keep count of the total number of characters input (excluding EOF).
I know I have to store the values in an array somehow using the malloc() function. I have to organize each character entered by keeping count of how many times that particular character was entered.
Thanks for the help!
Actually, since you are reading from standard input, there are at most 256 different possibilities. (You read in a char). Since that's the case, you could just statically allocate 256 integers for counting. int charCount[256]; Just initialize each value to 0, then increment each time a match is input.
Alternatively, if you must have malloc, then:
// This code isn't exactly what I'd turn in for homework - just a starting
// point, and non-tested besides.
int* charCount = (int*) malloc(sizeof(int) * 256); // Allocate 256.
for (int i = 0; i < 256; i++) charCount[i] = 0; // Initialize to 0.
// Counting and character input go here, in a loop.
int inputChar;
// Read in inputChar with a call to getChar(). Then:
charCount[inputChar]++; // Increment user's input value.
// Provide your output.
free(charCount); // Release your memory.
Here is a possible solution:
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
int
main(void)
{
int count[256] = {0};
char *l, *lp;
while (scanf(" %ms", &l) != EOF) {
for (lp = l; *lp; lp++)
count[(int)*lp]++;
free(l);
}
for (int i = 0; i < 256; i++) {
if (isprint(i) && count[i])
printf("%c: %d\n", i, count[i]);
}
exit(EXIT_SUCCESS);
}
Compile:
c99 t.c
Run:
$ ./a.out
abc
ijk
abc
<-- Ctrl-D (Unix-like) or Ctrl-Z (Windows) for EOF
a: 2
b: 2
c: 2
i: 1
j: 1
k: 1