Read lines from a file into character arrays - c

I'm completely new to C and I'm working on a program which has to read in 3 lines from a text file(two numbers and a mathematical symbol) and write out the result. So for example:
The text file looks like:
1
4
*
and my program should be able to read the 3 lines and write out something like "1*4 = 4" or something.
I managed to get to a point where i can read the 3 lines in and show them on screen, so I thought I should put the two numbers in one array and the symbol in another one. The problem is, that I tried to see if the arrays contain the numbers I put in them and my output has some huge numbers in it and I'm not sure why.
Here's the code i wrote:
#include <stdio.h>
#include <io.h>
#include <string.h>
int main(void)
{
int res = 1; /*Creates an integer to hold the result of the check for the file*/
const char *file = "input.txt"; /*String holding the name of the file with the input data*/
res = access(file,R_OK); /*Checks if the file "input.txt" exists*/
if(res == -1)
{ /*IF the file doesn't exist:*/
FILE *input = fopen("input.txt","w"); /*This creates a file called "input.txt" in the directory of the program*/
char write[] = "1\n1\n+"; /*This variable holds the string that's to be written to the file*/
fprintf(input,"%s",write); /*This writes the variable "write" to the file*/
printf("input.txt file created!"); /*Tells you the file is created*/
fclose(input); /*Closes the file after it's done*/
}
else
{ /*IF the file exists:*/
FILE *f = fopen("input.txt","r");
//char line[ 5000 ];
//while ( fgets ( line, sizeof line, f ) != NULL )
//{
// fputs ( line, stdout );
//}
char line[5000];
char nums[2];
char symbol[1];
int i = 0;
while(fgets(line,sizeof line,f)!=NULL)
{
i++;
if(i < 3)
{
fputs(nums,f);
}
else
{
fputs(symbol,f);
}
printf("%d,%d",nums,symbol);
}
printf("\n\n\n");
scanf("\n");
}
return 0;
}
Any help would be greatly appreciated!
Thank you in advance
If you require any more information i will provide it.

This is a self-explanatory algorithm. Also, here is the code that does the operation you are looking for. Generally, the complex operations are accomplished using stack, push and pop method. Once the operators are pushed. One need to apply the BODMAS rule,to evaluate the expression. Since the problem given to you is simple, a simple expression evaluation. This can be simply achieved by FIFO. Here is the algorithm, general explanation. Afterwards, the code is present. This code is well tested.You can extend it to do operations like +,-,division /, %, etc. If you like my answer please appreciate.
#include "stdio.h"
int main(int argc, char *argv[])
{
FILE *fp_op;
int buff[2]; /** assuming a simple operation, thus the buffer size is 3 only, the last one is to store the NULL **/
char operat_buff[2]; /** assuming this operation we can extend it to evaluate an expression **/
fp_op = fopen("calc.txt","rb");
if ( fp_op == 0 )
{
perror("The file doesn't exist to calculate\r\n");
goto error;
}
/** Read the two numbers here **/
fscanf(fp_op,"%d",&(buff[0]));
printf("The buff[1] = %d\r\n",buff[0]);
fscanf(fp_op,"%d",&(buff[1]));
printf("The buff[1] = %d\r\n",buff[1]);
/** read the next line now \n **/
operat_buff[0] = fgetc(fp_op);
/** read the actual character now **/
operat_buff[0] = fgetc(fp_op);
printf("The operat_buff[0] = %d\r\n",operat_buff[0]);
/** Read operation completed **/
/** use switch here **/
switch(operat_buff[0])
{
case '*':
printf("The multiplication result=%d\r\n",buff[0]*buff[1]);
break;
case '+':
printf("The Addition result=%d\r\n",buff[0]+buff[1]);
break;
default:
printf("Add more operations\r\n");
}
return 0;
error:
return -1;
}
I assume that the calc.txt was something like this.
calc.txt
3
5
*
Note: This code is compiled and verified.It compiles with zero warnings. It does the error checking too. You can directly copy and paste it.

What are you reading from the files are simply characters codes: the program has no way of figuring by itself that the character "4" corresponds to the integer number 4. The %d placeholder of printf expects int variables, or it won't work.
If you want just to print the characters you have to save them in char variables (or a char array) and use the placeholder %c in printf. If you want to actually use the numbers and symbols in your program you have more work to do.
Not only in C, but I think in most languages you have to "parse" the characters to numbers.
In C you can use the functions atoi or atol (you have to #include <stdlib.h>) in order to do this conversion.
In order to parse the symbol I'm afraid you will have to use an if or a switch to read the character and perform the operation accordingly.
For example your loop could look like:
while(fgets(line,sizeof line,f)!=NULL)
{
int op1;
int op2;
int res;
char symbol;
i++;
switch (i) {
case 1:
//First line is first operand
op1 = atoi(line);
printf("op1 %d\n",op1);
break;
case 3:
//Second line is second operand
op2 = atoi(line);
printf("op2 %d\n",op2);
break;
//Fifth line is the operator, could be +,-,%./ or anything
case 5:
symbol = line[0];
printf("operand %c\n",symbol);
switch(symbol) {
case '+':
res = op1+op2;
break;
case '-':
res = op1-op2;
break;
default:
//operation not defined, return
return;
}
printf("%d%c%d = %d",op1,symbol,op2,res);
}
}

printf("%d,%d",nums,symbol);
In your code nums and symbol are strings, you can't print them with %d. What you are getting are the addresses of the nums and symbol arrays, respectively - even if that's not the right way of printing an address.
You'll likely want to convert them to integers, using strtol or sscanf and then use those to perform the computation.

Related

Processing file extensions in C

I'm developing some code in C that reads a file extension and stores it as a code in a byte together whether a text file or binary file is being processed. Later I wish to recover the file extension that is encoded in a byte.
As a test I created a loop in the main function where I can test out the function fileExtenCode(), which is in the second listing.
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#define EXLEN 9
#define EXNUM 8
typedef unsigned char BYTE;
bool fileExtenCode(char*, BYTE*, int*);
int main(void) {
char fileExten[EXLEN];
BYTE code;
int bin;
for (;;) {
printf("Type file extension: ");
scanf_s("%s", fileExten, EXLEN);
if (fileExten[0] == '.') break;
printf("%s\n", fileExten);
code = 0;
bin = 0;
bool extFound = fileExtenCode(fileExten, &code, &bin); // <== (1)
if (extFound) printf("Extension found: TRUE\n");
else printf("Extension found: FALSE\n");
printf("%s%d", "Code: ", code);
if (bin) printf(" binary file\n");
else printf(" text file\n");
printf("\n");
printf("Type code: ");
int icode;
scanf_s("%d", &icode);
code = icode;
bin = -1;
fileExtenCode(fileExten, &code, &bin); // <== (2)
printf("%s", fileExten); // <== (5)
printf("\n");
}
return 0;
}
The function that I'm trying to test is as follows:
bool fileExtenCode(char* ext, BYTE* code, int* binary) {
char *fileEx[EXNUM] = {
"jpg1", "txt0", "html0", "xml0", "exe1", "bmp1", "gif1", "png1"};
if (*binary < 0) { // <== (3)
ext = fileEx[*code]; // <== (4)
return true;
}
size_t extLen = strlen(ext);
for (BYTE i = 0; i < EXNUM; i++) {
if (strncmp(fileEx[i], ext, extLen) == 0) {
*binary = (fileEx[i][extLen] == '1') ? 1 : 0;
*code = i;
return true;
}
}
return false;
}
The idea is that you pass a string with the file extension to fileExtenCode() in statement (1) in main, and the function searched for that extension in an array, and if found returns true together with the code argument indicating the position in array of file extensions and the binary flag as 0 or 1 indicating if the file is text or binary. A '0' or '1' immediately follows file extension in the array. If the extension is not found, the function returns with false and the return values in the arguments have no meaning.
So far so good, and this part works correctly. However, in using the function in reverse to recover the file extension given the input value of code, it fails when called with statement (2) in main. In this case binary is set to -1, and then the function is called and the condition at (3) is now true and ext in (4) recovers the file extension. This is confirmed when inserting a temporary print statement immediately after (4), but this value is not returned in (5) back in main, and an old input value is instead printed.
Obviously there is a problem with pointers, but I cannot see an obvious way of fixing it. My question is how to correct this without messing up the rest of the code, which is working correctly? Note that char* ext and BYTE* code are used for both input and output, whilst int* binary is used as an input flag and returns no useful value when set to -1.
Once this problem is fixed, then it should be relatively easy to separate the binary flag from the extension when the binary flag is set to -1. Eventually I plan to have many more file extensions, but not until this is working correctly with a sample of 8.
Getting help in fixing this problem would be most appreciated.
OK, many thanks pmg, that works, except that I have to use:
strcpy_s(ext, EXLEN, fileEx[*code]);
as the Visual Studio 2022 compiler flags an error. This also solves a warning I was getting when I declared the array *fileEx[EXNUM] with the const keyword.
In my haste last night I omitted to include the statement:
if (*code >= EXNUM) return false;
immediately after (3) to trap the case when *code goes out of bounds of *fileEx[EXNUM].

How to iterate through files in c?

I have to write a function that given two files, compares them both and writes on a third file each word they have in common, I tried with this one, actually making it write on terminal to see if it works, it actually iterates trough the second file but it only compares the first word of the first file, any suggestions?
void fileCopy(FILE *f1,FILE *f2){
char fileString1[100], fileString2[100];
while(!feof(f1)){
fscanf(f1,"%s",fileString1);
while(!feof(f2)){
fscanf(f2,"%s",fileString2);
if(!strcmp(fileString1,fileString2)) printf("%s ",fileString1);
}
}
}
while(!feof(f2)) loops until the end of the second file. You must iterate through both files simultaneously. Instead of these while(!feof... you should be checking the result of each fscanf.
A simple pseudo code example:
while(1)
{
int fscanf1_result = fscanf(f1, ...);
int fscanf2_result = fscanf(f2, ...);
if(fscanf1_result != 1 || fscanf2_result != 1)
{
break;
}
/* rest of the code here */
};

How do I read a text file and store it in an array in C programming (values seperated by a comma)?

I need help with getting datapoints, x and y values from a txt file into two arrays.
Currently, the text file consists of 5 lines like:
0.116
0.118
0.12
0.122
0.124
This is my code:
#include <stdio.h>
#include <stdlib.h>
main(void)
{
FILE *inp; /* pointer to input file */
double item;
int cnt=0,y,d,i;
double array[300],swap;
/* Prepare files for input */
inp = fopen("testdoc.txt", "r");
/* Read each item */
while ( (fscanf(inp, "%lf", &item) == 1) && (!feof(inp)) ) {
array[cnt] = item;
cnt++;
}
for (int i = 0; i < cnt; i++)
{
printf("%lf\n",array[i]);
}
printf("The total number of inputs is %d",cnt);
fclose(inp); /* Close the files */
return (0);
}
This only reads the first half of the file, which are the x values. Of which output is
0.116000
0.118000
0.120000
0.122000
The total number of inputs is 4
However, I want to read a text file and store the values in two different arrays for x and y values.
The new text file will look like this
0.116,-0.84009
0.118,4.862
0.12,-1.0977
0.122,0.22946
0.124,3.3173
How do i go changing my code above to recognize the Y values after "," sign? And to add both into two arrays at once?
I tried compiling your code posted on pastebin and received an error because of a missing bracket in your while statement.
That's an easy fix.
The larger issue is in the condition of the while loop.
fscanf returns the number of input items converted and assigned on each call.
When you modified your code to return two values, the condition in the while loop fscanf(inp, "%lf,%lf", &v1,&v2) == 1 would fail and the loop will not be entered.
Please modify the while statement to (have included the missing "(" too)..
while ( (fscanf(inp, "%lf, %lf", &v1, &v2) == 2) && (!feof(inp)) )
and you should be good to go!!!
In addition it would be a good practice to include the return type of int for the main function.

Why does my function return 0 instead of the number of lines in a file?

I have written a function that is supposed to read the number of sentences in a .txt file, but when the function is called and done, it gives me a value of 0.
This program over all has 3 more functions to figure out different properties of the file and I have them working great. This one is laid out the same way I wrote my other functions just looking for some advice on why I am getting 0 as my number of sentences.
void ptrCntS (FILE* sp1, int sCount)
{
char sentence = 'O';
int myChr;
if (!(sp1 = fopen("Hello.txt", "r")))
{
printf("error opening Hello.txt");
return(1);
}
while ((myChr = fgetc(sp1)) != EOF)
{
if ('.')
{
sentence ='O';
}
else if (sentence == 'O')
{
sCount++;
sentence = 'I';
}
}
fclose(sp1);
printf ("Total number of sentences are:\t%d", sCount);
return;
}
instead of return use return(sCount);
and assign the return value to some int variable in calling function
like
int sentCount;
.
.
.
sentCount=ptrCntS (param1,param2);
if ('.') is always true, thus else... code never reached. Use if( myChr == '.' ) instead.
Function compiles now and runs properly. This function is being called from a switch in a previous function where I had my addresses set and included my print statement for the totals so that I would not have to write another function in the end to call on all my counts and print their results. Instead I set my case 'A': to call all of my counting functions(in this case that is what the original code is) and than display my results. I am sorry for any lengthiness or my hard to understand writing I am new to the C language and I am having a hard time grasping the literature but making some process on understanding the syntax.

Extracting timings from a multidimensional array and writing to a file in c

I'm having trouble extracting the timings from a .srt (subtitle) file and writing it to another file called output.srt. When i run the following i get some funky stuff written onto the output file.
// where hr=hours,mn=minutes,sc=seconds,ms=mili seconds
#include <stdio.h>
#define LINES 50
#define CHARAC 80
int main(void){
FILE *in;
FILE *out;
char text[LINES][CHARAC];
char timings[LINES][CHARAC];
int i=0,lines=0,items=0;
int hr=0,mn=0,sc=0,ms=0,hr2=0,mn2=0,sc2=0,ms2=0;
in=fopen("file2.srt","r");
out=fopen("output.srt","w");
while (!feof(in)){
fgets(text[i],80,in);
items=sscanf(text[i],"%d:%d:%d,%d --> %d:%d:%d,%d ",&hr,&mn,&sc,&ms,&hr2,&mn2,&sc2,&ms2);
//------------------------------------->edited<----------------------------------
switch (items)
{
case 1: break;
case 8:
sprintf(timings[i],"%d:%d:%d,%d --> %d:%d:%d,%d",hr,mn,sc,ms,hr2,mn2,sc2,ms2);
break;
case 0: break;
}
//------------------------------------->edited<----------------------------------
++i;
}
lines=i;
for (int i=0;i<lines;i++){
fprintf(out,"%s\n",timings[i]);
}
fclose(in);
fclose(out);
return 0;
}
how do I go about extracting those first 10 timings?
If this is on windows (or MSDOS) the open modes need to be text:
in = fopen ("file2.srt", "rt");
out = fopen ("output.srt", "wt");
Secondly, the code isn't doing anything to react to the differently formatted lines. The first few data lines are:
1
00:00:30,909--> 00:00:32,775
Take a look at yourself.
2
00:00:34,066--> 00:00:37,681
Disconnect you from the seats,
lift yourself and take a look in the mirror.
So, naturally, the first sscanf isn't going to fill in most of the fields. Here's the output I got (for the corresponding lines):
1:0:0,0 --> 0:0:0,0
0:0:30,909 --> 0:0:32,775
0:0:30,909 --> 0:0:32,775
0:0:30,909 --> 0:0:32,775
2:0:30,909 --> 0:0:32,775
To fix this, you'll have to add logic which expects the proper number of elements, or at least reacts to them:
itms = sscanf(text[i],"%d:%d:%d,%d --> %d:%d:%d,%d ",&hr,&mn,&sc,&ms,&hr2,&mn2,&sc2,&ms2);
switch (itms)
{
case 1: // the first line
case 8: // the lines with the times
case 0: // the text lines
}
Edited to add a fixed version of your last edit:
#include <stdio.h>
#define LINES 50
#define CHARAC 80
int main(void){
FILE *in;
FILE *out;
char text[LINES][CHARAC];
char timings[LINES][CHARAC];
int i=0,lines=0,items=0;
int hr=0,mn=0,sc=0,ms=0,hr2=0,mn2=0,sc2=0,ms2=0;
in=fopen("file2.srt","rt");
out=fopen("output.srt","wt");
while (!feof(in))
{
if (!fgets(text[i],80,in))
break;
items = sscanf(text[i], "%d:%d:%d,%d --> %d:%d:%d,%d ", &hr,&mn,&sc,&ms,&hr2,&mn2,&sc2,&ms2);
switch (items)
{
case 1: break;
case 8:
sprintf(timings[i],"%d:%d:%d,%d --> %d:%d:%d,%d",hr,mn,sc,ms,hr2,mn2,sc2,ms2);
++i; // advance only when a valid line is seen
break;
case 0: break;
}
}
lines=i;
for (i=0; i<lines; i++){
fprintf(out,"%s\n",timings[i]);
}
fclose(in);
fclose(out);
return 0;
}
The first thing I notice is that you're not checking the result of the sscanf(). You should check the return code to make sure all eight items were scanned in, and only sprintf() to timings[] if the data was scanned correctly.
You need to check the return value from sscanf() to see if the line matched. I downloaded your sample file:
1
00:00:30,909--> 00:00:32,775
Take a look at yourself.
2
00:00:34,066--> 00:00:37,681
Disconnect you from the seats,
lift yourself and take a look in the mirror.
Only some of these lines will return 8 from sscanf() as the number of matches, so test for that. Of course, this will fail if text line matches that, too!
Better would be to look for a blank line (except for the first), then an integer on one line, then the timing. Match only if all three work.

Resources