Parsing and splitting a string from txt file in C - c

I'm new into C and I got an assignment to read line by line from .txt file and parse some strings into matrix where first line is first row, second line is second row etc. This is what I have in my text.txt file:
07 45 C4 16 0F 02 19 0I 17 0G
09 45 C4 15 0E 03 11 0A 12 0B 13 0C
13 45 C4 13 0C 03 19 0I 11 0A 17 0G 14 0D 16 0F
05 45 C4 18 0H 01 12 0B
This is what I was able to do so far:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *Read(char filename[]);
void split(char *content);
int main(void){
char filename[] = "text.txt";
char *content = Read(filename);
split(content);
return 0;
}
char *Read(char filename[]){
char *buffer;
long size;
FILE *log = fopen("text.txt", "r");
fseek(log, 0, SEEK_END);
size = ftell(log);
rewind(log);
buffer = (char*) malloc(sizeof(char) * size);
fread(buffer, 1, size, log);
fclose(log);
return buffer;
}
void split(char *content){
char *buffer = strtok(content, " ");
while(buffer != NULL){
printf("%s\n", buffer);
buffer = strtok (NULL, " ");
}
}
I would really appreciate comments in code because I'm rookie and it would help me to better understand some things.

To give you an idea of how it works, I wrote this snippet which manually read the line in that array, supposing that we already know the desired results.
The following approach cannot be considered the right one. Ideally you would have a series of rules to split the string, in the following however you have to set the scanf format manually for each line that you want to read.
Remember to check the return value of scanf, here we should ensure that we have read 7 elements.
int main(void) {
FILE *log;
char buffer[SIZE];
char line[SIZE];
char array[10][10];
if ((log = fopen("text.txt", "r")) == NULL){
fprintf(stderr, "Can't open input file!\n");
return(1);
}
while(fgets(buffer, sizeof(buffer), log)){
int ret = sscanf(buffer, "%2s%2s%2s%4s%2s%4s%4s", array[0], array[1], array[2], array[3], array[4],array[5], array[6]);
printf("read %d elements\n", ret);
if (ret != 7) {
return(1);
}
printf("%s", buffer);
}
int i;
for (i=0; i < 6; i++)
printf("%s\n", array[i]);
fclose(log);
return 0;
}

Related

File reading with fgetc in C

I have a simple file reading algorithm but it's not returning the values that are in the file. The below is the code. The input txt values are 200 53 65 98 183 37 122 14 124 65 67 but the code is returning 48 48 32 53 51 32 54 53 32 57 56 32 49 56 51 32 51 55 32 49 50 50 32 49 52 32 49 50 52 32 54 53 32 54 55 -1 and I'm not sure why.
It should be taking the read in values and putting it into the linked list.
int readInputFile(char *fileName, LinkedList *list)
{
FILE *inputFile = fopen(fileName, "r");
int ch;
if (inputFile == NULL)
{
perror("Could not open file");
}
else
{
while (ch != EOF)
{
ch = fgetc(inputFile);
printf("%d", ch);
if (ferror(inputFile))
{
perror("Error reading from source file.");
}
else
{
//printf("%d", ch);
insertLast(list, ch);
}
}
}
}
Your code has undefined behavior because you test while (ch != EOF) with ch uninitialized the first time. You should write:
while ((ch = fgetc(inputFile)) != EOF) {
[...]
Yet the problem is you read individual bytes instead of parsing the file contents for numbers expressed as decimal integers. You should use fscanf() to convert the text into integers.
You also forgot to close the file, causing resource leakage.
Here is a modified version:
#include <errno.h>
#include <stdio.h>
#include <string.h>
int readInputFile(const char *fileName, LinkedList *list)
{
FILE *inputFile = fopen(fileName, "r");
if (inputFile == NULL) {
fprintf(stderr, "Could not open file %s: %s\n",
fileName, strerror(errno));
return -1;
} else {
int value, count = 0;
char ch;
while (fscanf(inputFile, "%d", &value) == 1) {
printf("inserting %d\n", value);
insertLast(list, value);
count++;
}
if (fscanf(inputFile, " %c", &ch) == 1) {
fprintf(stderr, "File has extra bytes\n");
}
fclose(inputFile);
return count; // return the number of integers inserted.
}
}
You read a character with fgetc() but you want to read a number which you do with int d; fscanf(inputFile, "%d", &d).

Writing half of an int array into a new text file

In my program, I am trying to opens the text file provided at the command-line, and then creates two new text files values1.txt and values2.txt. The file from the command line contains 100 unique integer numbers. Half of the numbers are copied into values1.txt, the other half is copied into values2.txt.
However, when I tried to do it for values1.txt, I got the following values:
101
32758
0
0
176197744
32764
3
0
176197728
32764
0
0
-78325960
32758
0
0
1
0
-78326000
32758
0
0
1700966438
0
-78325096
32758
176197896
32764
176197952
32764
-78326000
32758
0
0
-80547345
32758
0
0
176197952
32764
0
0
0
0
0
0
-78326000
32758
-82942073
32758
8
Here is my code:
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
int cfileexists(const char * filename){
/* try to open file to read */
FILE *file;
if (file = fopen(filename, "r")){
fclose(file);
return 1;
}
}
int main(int argc,char*argv[]){
char *p= argv[1];
int numArray[100];
int i=0;
int sum1arr[50];
int sum2arr[50];
if (! cfileexists(p)){
printf("Error, unable to locate the data file %s\n", p);
return 100;
}
for(i;i<100;i++){
FILE *stream=fopen(p,"r");
while(!feof(stream)){
fscanf(stream,"%d",&numArray[i]);
}
FILE * fPtr = NULL;
fPtr = fopen("values1.txt", "w");
for(int j=0;j<50;j++){
fprintf(fPtr,"%d\n",numArray[j]);
}
}
}
For comparison; this is the source txtfile:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
The for statement has too many cycles, you should use the read cycle to also write, you also can use fscanf return to verify whe the file reaches it's end. If you don't need to save the values you can even use on singe int to temporarily store the value till it's written.
Here is a possibe implementation with comments:
Live demo
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int cfileexists(const char *filename)
{
/* try to open file to read */
FILE *file;
if ((file = fopen(filename, "r")))
{
fclose(file);
return 1;
}
return 0; //return 0 if file not found
}
int main(int argc, char *argv[])
{
if(argc != 2){ //check number of arguments
puts("Wrong number of arguments");
return(EXIT_FAILURE); //EXIT_FAILURE macro is more portable
}
FILE *stream;
FILE *fPtr = NULL;
FILE *fPtr2 = NULL;
int numArray[100];
int i = 0;
fPtr = fopen("values1.txt", "w");
fPtr2 = fopen("values2.txt", "w");
//you can use fopen to check file nstead of the
//function, it returns null if no file is opened
if (!(stream = fopen(argv[1], "r")))
{
perror("Error, unable to locate the data file"); //also prints error signature
return EXIT_FAILURE;
}
//check input, stop when there is nothing else to read
while (fscanf(stream, "%d", &numArray[i]) == 1 && i < 100)
{
if(i < 50)
fprintf(fPtr, "%d\n", numArray[i]); //write to file 1
else
fprintf(fPtr2, "%d\n", numArray[i]); //write to file 2
i++;
}
fclose(stream);
fclose(fPtr);
fclose(fPtr2);
}
Here's a different approach that uses getline():
#include <stdio.h>
#include <stdlib.h>
#define SPLIT_POINT 50
int main(void) {
char filename[] = "test";
FILE *fp = fopen(filename, "r");
if (!fp) {
fprintf(stderr, "Couldn't open %s\n", filename);
}
// Check file open (as above) left out for brevity
FILE *out1 = fopen("values1.txt", "w");
FILE *out2 = fopen("values2.txt", "w");
char *line = NULL;
size_t n = 0, i = 0;
ssize_t len = 0;
while ((len = getline(&line, &n, fp)) != EOF) {
// Select which output file to write to
FILE *out = i < SPLIT_POINT ? out1 : out2;
// getline includes the newline - remove this
if (i == SPLIT_POINT - 1 && len > 0) {
line[--len] = 0;
}
// Write to the relevant output file
fprintf(out, "%s", line);
i++;
}
fclose(fp);
fclose(out1);
fclose(out2);
free(line);
return 0;
}
If you don't care about removing newlines, you could simplify the getline() call - just don't bother with the len variable.

Convert BIGNUM into raw binary file

I want to convert this hex string into raw binary file using BIGNUM's BN_bn2bin function
BN_hex2bn(&asn1hash, "3031300D060960864801650304020105000420BC5F9353CBB9DCAE86B9F8F68C1C95856DB836ACA2E00C9319716CDF4DD0F5BA");
char *buf = (unsigned char *)malloc(BN_num_bytes(asn1hash));
BN_bn2bin(asn1hash, buf);
FILE *fp;
fp = fopen("ASn1Hash","wb+");
fputs(buf, fp);
fclose(fp);
But why is it that only "30 31 30 0D 06 09 60 86 48 01 65 03 04 02 01 05" is ever outputted into the file?
thanks fixed the code
BN_hex2bn(&asn1hash, "3031300D060960864801650304020105000420BC5F9353CBB9DCAE86B9F8F68C1C95856DB836ACA2E00C9319716CDF4DD0F5BA");
int num_bytes = BN_num_bytes(asn1hash);
char *buf = (unsigned char *)malloc(num_bytes);
BN_bn2bin(asn1hash, buf);
FILE *fp;
fp = fopen("ASn1Hash","wb+");
fwrite(buf, 1, num_bytes, fp);
fclose(fp);

Reading from file in C including char and integer

How to read and store each column in the following text from a file into an array
A17ke4004 44 66 84
A17ke4005 33 62 88
A17ke4008 44 66 86
The first column should be string and the rest should be integer
Here is a simple code that do the job.
First put your text inside a test.txt file, save it in C source code path.
test.txt
A17ke4004 44 66 84
A17ke4005 33 62 88
A17ke4008 44 66 86
Code
#include <stdio.h>
int main (void)
{
FILE *fp = NULL;
char *line = NULL;
size_t len = 0;
size_t read = 0;
char string[10][32];
int a[10], b[10], c[10];
int count = 0;
fp = fopen("test.txt", "r");
if(fp != NULL){
while((read = getline(&line, &len, fp)) != -1){
sscanf(line, "%s%d%d%d", string[count], &a[count], &b[count], &c[count]);
printf("<%s> - <%d> - <%d> - <%d>\n", string[count], a[count], b[count], c[count]);
count++;
}
}else{
printf("File can't open\n");
}
return 0;
}
Compile, Run
gcc -Wall -Wextra te.c -o te
./te
If you have more than 10 lines you should increase the arrays dimension.
Hope this help you.

C - Reverse Converter Process

Context:
I'm trying to reverse the process of a c converter. This is the original converter:
#include <stdio.h>
int main(void) {
FILE *f = fopen("input.bin", "rb");
fseek(f, 0, SEEK_END);
int s = ftell(f);
rewind(f);
FILE *o = fopen("output.txt", "wb");
int i;
for(i = 0; i < s / 4; i++) {
unsigned int u;
fread(&u, sizeof(u), 1, f);
fprintf(o, "u32[%d] = 0x%08x;\n", i, u);
}
fclose(o);
fclose(f);
return 0;
}
What it does is it creates a new file called output.txt and converts the .bin file to bytes in a order like this:
u32[0] = 0x53555441;
u32[1] = 0x6373b848;
u32[2] = 0x74654e65;
u32[3] = 0x83486f53;
u32[4] = 0x0ebe60ec;
u32[5] = 0x48000000;
u32[6] = 0x40245c8d;
u32[7] = 0x24448948;
u32[8] = 0xda894840;
u32[9] = 0x244c8d48;
u32[10] = 0x024fbf10;
u32[11] = 0xc0310000;
u32[12] = 0x482444c7;
u32[13] = 0x74656b63;
Question:
Now, what I'm trying to do is the opposite. So, I'm trying to convert the output bytes of the above converter to a .bin file again, like its original state.
I tried this, but I'm stuck on the loop part:
#include <stdio.h>
int main(void) {
FILE *f = fopen("loader.txt", "rb"); // INPUT
fseek(f, 0, SEEK_END);
int s = ftell(f);
rewind(f);
FILE *o = fopen("loader.bin", "wb"); // OUTPUT
int i;
for(i = 0; i < s / 4; i++) {
// grab u32 bytes from loader.txt and convert into a .bin
}
fclose(o);
fclose(f);
return 0;
}
Can anyone help me out with this? Would be amazingly appriciated.
Edit
#include <stdio.h>
int main(void) {
FILE *f = fopen("loader.txt", "rb"); // INPUT
rewind(f);
FILE *o = fopen("loader.bin", "wb"); // OUTPUT
int i;
for(i = 0; i < s / 4; i++) {
fgets(f);
sscanf(f);
}
fclose(o);
fclose(f);
return 0;
}
Here is code which seems to do the job:
#include <stdio.h>
int main(void)
{
const char i_file[] = "loader.txt";
const char o_file[] = "loader.bin";
FILE *f = fopen(i_file, "rb"); // INPUT
if (f == 0)
{
fprintf(stderr, "failed to open file '%s' for reading\n", i_file);
return 1;
}
FILE *o = fopen(o_file, "wb"); // OUTPUT
if (o == 0)
{
fprintf(stderr, "failed to open file '%s' for writing\n", o_file);
return 1;
}
char line[1024];
int lineno = 0;
while (fgets(line, sizeof(line), f) != 0)
{
int u32num;
unsigned int value;
lineno++;
if (line[0] == '\n')
continue; // Blank lines ignored
if (sscanf(line, "u32[%d] = %x", &u32num, &value) == 2)
{
fseek(o, u32num * sizeof(value), SEEK_SET);
if (fwrite(&value, sizeof(value), 1, o) != 1)
{
fprintf(stderr, "Failed to write 0x%.8X to offset %d in %s\n",
value, u32num, o_file);
break;
}
}
else
{
fprintf(stderr, "Input line %d in %s is mal-formatted: %s", lineno, i_file, line);
break;
}
}
fclose(o);
fclose(f);
return 0;
}
When run on the sample data from the question (loader.txt):
u32[0] = 0x53555441;
u32[1] = 0x6373b848;
u32[2] = 0x74654e65;
u32[3] = 0x83486f53;
u32[4] = 0x0ebe60ec;
u32[5] = 0x48000000;
u32[6] = 0x40245c8d;
u32[7] = 0x24448948;
u32[8] = 0xda894840;
u32[9] = 0x244c8d48;
u32[10] = 0x024fbf10;
u32[11] = 0xc0310000;
u32[12] = 0x482444c7;
u32[13] = 0x74656b63;
the output file (loader.bin) is:
$ odx loader.bin
0x0000: 41 54 55 53 48 B8 73 63 65 4E 65 74 53 6F 48 83 ATUSH.sceNetSoH.
0x0010: EC 60 BE 0E 00 00 00 48 8D 5C 24 40 48 89 44 24 .`.....H.\$#H.D$
0x0020: 40 48 89 DA 48 8D 4C 24 10 BF 4F 02 00 00 31 C0 #H..H.L$..O...1.
0x0030: C7 44 24 48 63 6B 65 74 .D$Hcket
0x0038:
$
where odx is simply a home-grown hex dump program (you could use od or xxd or other programs to achieve similar results). Taking the original conversion code verbatim (it compiled cleanly under my stringent compilation options — well done), and copying loader.bin to input.bin, the output is:
u32[0] = 0x53555441;
u32[1] = 0x6373b848;
u32[2] = 0x74654e65;
u32[3] = 0x83486f53;
u32[4] = 0x0ebe60ec;
u32[5] = 0x48000000;
u32[6] = 0x40245c8d;
u32[7] = 0x24448948;
u32[8] = 0xda894840;
u32[9] = 0x244c8d48;
u32[10] = 0x024fbf10;
u32[11] = 0xc0310000;
u32[12] = 0x482444c7;
u32[13] = 0x74656b63;
This is the same as the original input file, so the pair of programs can round-trip their data (run the two programs in turn and get as final output the data stored as the original input). Note that the code has not been tested on a binary file with a length that is not a multiple of 4 bytes; there are issues to worry about there.

Resources