Reading unsigned char from .txt file using fread give different values - c

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++;
}

Related

How many characters is fscanf scanning in my code?

I'm using a for loop, which I want to iterate a number of times equal to the number of characters scanned by scanf. However, it seems to run too many times. The code was originally written to print to phrase "We are in 2019", which it does, but now I need to use it for something else. I added in the line: printf("%i",i);
to see how many times it was going through the for loop. It seems to be running 8 times for each run of the while loop, regardless of how long the word scanned was.
#include <stdio.h>
#include <stdlib.h>
int main() {
char* word = malloc(sizeof(char) * (46)); // create a char array
FILE* fp;
fp = fopen("file.txt", "w+");
fputs("We are in 2019", fp);
rewind(fp); // sets to start of file
while(fscanf(fp, "%s", word) != EOF) {
for(int i = 0; i < sizeof(word) / sizeof(word[0]); i++) {
printf("%c", word[i]);
printf("%i", i);
}
printf("\n");
}
fclose(fp);
return (0);
}
The output is:
W0e1234567
a0r1e234567
i0n1234567
200112934567
So I can see it's running the for loop 8 times for each run for each run of the while loop.
Am I misunderstanding how fscanf works? i thought it stopped at a whitespace, and only stored the preceding characters... e.g. first it would scan "We" then store it as a 3 character array in "words", then scan "are" in a 4 character array in "words" and so on. What is really happening?
It is stopping at whitespace.
Apparently you have 64 bit pointers. The variable word is a pointer, so sizeof(word) is 8. Since sizeof one character is 1, sizeof(word) / sizeof(word[0]) is 8.
So, the first time fscanf returns, it has read "We" into the buffer. Then it loops for i from 0 to 7.
i = 0
printf("%c", word[i]); //=> 'W'
printf("%i", i); //=>0
i = 1
printf("%c", word[i]); //=> 'e'
printf("%i", i); //=>1
i = 2
printf("%c", word[i]); //=> '\0' so nothing
printf("%i", i); //=>2
i = 3
printf("%i", i); //=>3
i = 4
printf("%i", i); //=>4
i = 5
printf("%i", i); //=>5
i = 6
printf("%i", i); //=>6
i = 7
printf("%i", i); //=>7
so that is how you get:
W0e1234567
You would see the desired output if your loop looked like this:
while(fscanf(fp, "%s", word) != EOF) {
puts(word);
}
sizeof(word) will not give you the size of the array. It gives the size of the pointer char *word.
It would be simpler to avoid memory allocation, and the size of the array isn't really relevant anyway.
#include <stdio.h>
#include <stdlib.h>
int main() {
char word[46]; // local array
FILE* fp = fopen("file.txt", "w+");
if(fp == NULL) {
return 1; // or better error report
}
fputs("We are in 2019", fp);
rewind(fp);
while(fscanf(fp, "%45s", word) == 1) { // restrict length, check the scan worked
for(int i = 0; word[i] != 0; i++) { // finish when the string terminator is found
printf("%c", word[i]);
}
printf("\n");
}
fclose(fp);
return 0;
}
Program output:
We
are
in
2019
Several remarks can be done on your code
by definition sizeof(char) is 1, so your malloc(sizeof(char) * (46)) can be simplified to be malloc(46). Note you can also use an array char word[46];
fscanf(fp, "%s", word) is very dangerous, if the read word longer than 45 characters you write out of word with an undefined behavior, limit the size doing fscanf(fp, "%45s", word)
As said in the remarks sizeof(word) / sizeof(word[0]) do not return the length of your word, you can just stop when word[i] is 0
to print the index just after each character do not produces a very readable result, are you sure you want that ?
why do you not directly print the word by (f)puts or printf with the format %s and get the length of the string using strlen (if you want to know it) ?
I want to iterate a number of times equal to the number of characters scanned by scanf.
scanf scans more than the number of characters in returns in the string, the spaces are bypassed silently. Only one thing is sure, when you reach the end of the file without error the number of characters scanned by scanf if the size of the file.

An efficient way of reading integers from file

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

Odd printing behavior in C

I'm trying to print out comma seperated values in my C program, but I think I keep getting memory allocations instead.
When running from the command line, this happens.
1
49 this is the response
10 this is the response
1
49 this is the response
10 this is the response
Here is my program:
void main(){
int j;
int idnum;
j = 0;
char entry[99];
do{
idnum = get_field(entry);
j++;
}
while(idnum!='\n' && idnum!= ',' && j!= MAXTYPES);
int recur = 0;
while (recur != 4){
printf("%4d\n", entry[recur]);
recur++;
}
printf("\nEnd of Input\n");
}
int get_field(char entry[]){
int idnum;
char n;
int j = 0;
char temp[45];
while ((n=getchar())!= EOF){
printf("%d this is the response\n",n);
}
return idnum;
}
Problems I see:
In get_field, you have not initialized idnum and returning it from the function.
In get_field, the while loop to read the data is strange. I am not sure what you are trying to accomplish. However, you if type 1 and then press Enter, two characters are added to the input stream: '1' and '\n'. You are reading them as char, using getchar, and printing them as int (by using the "%d" format).
That explains the output you are getting.
49 is the decimal representation of '1'.
10 is the decimal representation of '\n'
The return type of getchar is int. You should change the type of n in get_field to int from char. That could be source of problems depending on the platform you are working in.
With %d you are printing the ASCII values. ASCII value of 1 is 49 and of \n is 10.
These are what you are getting.
You may want to print them with %c.
Since n is a char type data.So,you've to use %c instead of %d Like this:
printf("%c this is the response\n",n);

Read from txt file and input to an array in C

I have my txt file
4
110
220
112
335
4 is the number of lines and 4*3 the number of int. I have to read "4" then read the remaining and input them into an array
This is what I have
void main(){
int a,n;
int i=0,j=0,k[30]; //
int *N;
FILE *fp = fopen("test.txt", "r");
if(fscanf(fp, "%d", &a) != 1) { //
// something's wrong
}
n=3*a; //3*a numbers in the file
N = malloc(3 * a * sizeof(int));
for(i = 0; i <n;++i) {
int result=fscanf(fp, "%d", &N[i] );
}
fclose(fp);
for(j=0;j<3*a;j++){
k[j]=N[j];
}
printf("%d",k[0]);
}
When I print k[0] it was supposed to print "1" but instead the whole line "110" is printed
Is there any other way to do this???
The format specifier %d does not specify a length, so fscanf will read as many digits as it can; this is why you get 110 instead of just 1.
If you specify a length, like %1d, it will only read as many digits as you tell it to:
for(i = 0; i <n;++i) {
int result=fscanf(fp, "%1d", &N[i] );
}
When you use fscanf with %d format parameter, it retrieves an integer type from the file. Since 110 and the others are all integers, it will directly fetch 110 from file.
So you can either use fscanf with %d parameters in a loop which iterates for a times, or if you want to get it character by character, you can use fscanf with %c parameter but it needs much more effort. So, you should use fscanf with %d parameter and fetch all digits from it by a loop for every number.
The fscanf(fp, "%d", &N[i] ) will catch a number and not a digit. So
fscanf(fp, "%d", &N[0] ) //will catch 110
fscanf(fp, "%d", &N[1] ) //will catch 220
...
If you want to catch digits in your array you have to use the following code:
for(i = 0; i <n;++i) {
int result=fscanf(fp, "%c", &N[i] );
if (isdigit (N[i])) N[i]-='0';
else i--;
}

reading unknown number of integers from stdin (C)

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)

Resources