Read file from different positions and put in an array in C - c

I want to read a file which looks like this:
Name=José, Age=21
Name=Antonio, Age=26
Name=Maria, Age=24
My problem is how can i read the names and ages from different positions and different lines and put in an array names[size] and the same thing for the ages ages[size].
I have this at the moment:
#include <stdio.h>
#define size 100
int main()
{
char ch = 0;
int i = 0;
char names[size];
char ages[size];
FILE *fp1;
fp1 = fopen("data.txt", "r");
if(fp1 == NULL)
{
printf("Error!");
return 1;
}
while((ch=fgetc(fp1)) != '=');
while((ch=fgetc(fp1)) != ',')
{
fscanf(fp1, "%s", names);
i++;
}
fclose(fp1);
printf("Names = %s", names);
return 0;
}
Can anyone explain me what is the best way to do it?

you need 2D-Array. E.g names[number of record][max length size + 1]
a way sample like this
#include <stdio.h>
#define size 100
int main(void){
int i = 0;
char names[size][128];
char ages[size][4];
FILE *fp1;
fp1 = fopen("data.txt", "r");
if(fp1 == NULL){
printf("Error!\n");
return 1;
}
while(i < size && 2 == fscanf(fp1, "Name=%127[^,], Age=%3[0-9]\n", names[i], ages[i])){
i++;
}
fclose(fp1);
int n = i;
for(i = 0; i < n; ++i)
printf("Names = %s, Ages = %s\n", names[i], ages[i]);
return 0;
}

Related

How to shuffle 2 different text file into 1?

#include <stdio.h>
int main(){
char temp[64];
FILE *fp1=fopen("data/1.txt","a");
FILE *fp2=fopen("data/2.txt","r");
while(fgets(temp,64,fp2)!=NULL){
fputs(temp,fp1);
}
fclose(fp1);
fclose(fp2);
return 0;
}
With such code I was able to combine 2 different text file into 1.
data/1.txt contents: abcdefghijk
data/2.txt contents: ABCDE
Outcome: abcdefghijkABCDE
However, I am struggling with shuffling 2 different text file.
Wanted result: aAbBcCdDeEfghijk
Followings are my current code.
#include <stdio.h>
#include <string.h>
int main(){
FILE *fp1,*fp2,*fp_out;
char ch1,ch2;
int result=1;
fp1=fopen("data/1.txt","r");
fp2=fopen("data/2.txt","r");
fp_out=fopen("data/out.txt","w");
//shuffling code area//
fclose(fp1);
fclose(fp2);
fclose(fp_out);
char buf[64]={};
fp_out=fopen("data/out.txt","r");
fgets(buf,64,fp_out);
if(!strncmp("aAbBcCdDeEfghijk",buf,64))
printf("PASS\n");
else
printf("FAIL\n");
fclose(fp_out);
return 0;
}
How can I design a code in "shuffling code area" in order to have outcomes like wanted result? I have thought about making 2 different FOR loops and combining but it kept showed an error.
This is some dirty way to do the job.
You can read the file which ever you want to write first character first and then read a character from second file and write both into third file one after the other.
Just adding extra code as per your need.
This just works for your case , not tested with many cases and corner cases.
#include <stdio.h>
#include <string.h>
int main(){
FILE *fp1,*fp2,*fp_out;
char ch1,ch2;
int result=1;
int file1_content_over = 0;
int file2_content_over = 0;
fp1 = fopen("data/1.txt","r");
fp2 = fopen("data/2.txt","r");
fp_out=fopen("data/out.txt","w");
//shuffling code area//
// read till file1_content_over or file2_content_over is not finished
while(! file1_content_over || !file2_content_over)
{
ch1 = fgetc(fp1);
ch2 = fgetc(fp2);
if(ch1 != EOF)
fputc(ch1,fp_out);
else
file1_content_over = 1;
if(ch2 != EOF)
fputc(ch2,fp_out);
else
file2_content_over = 1;
}
//shuffling code area//
fclose(fp1);
fclose(fp2);
fclose(fp_out);
char buf[64]={};
fp_out=fopen("data/out.txt","r");
fgets(buf,64,fp_out);
printf("buf = %s\n", buf);
if(!strncmp("aAbBcCdDeEfghijk",buf,strlen("aAbBcCdDeEfghijk")))
printf("PASS\n");
else
printf("FAIL\n");
fclose(fp_out);
return 0;
}
Working for me! Not the best optimized code, I didnt get to much time to that!
Main():
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX 100
int removingSPaces(char array[MAX], int sizeArray);
void orderChar(char bufFile1[MAX], char bufFile2[MAX], char bufOut[MAX], int maxSize, int sizeBuf1, int sizeBuf2);
int getChar(char buf[MAX], FILE *fp);
int main(){
FILE *fp1, *fp2, *fpOut;
char bufFile1[MAX] = {0}, bufFile2[MAX] = {0}, bufOut[MAX] = {0};
int sizeBuf1 = 0, sizeBuf2 = 0;
int maxSize=0;
if((fp1=fopen("file1.txt","r")) == NULL || (fp2=fopen("file2.txt","r")) == NULL || (fpOut=fopen("fileOut.txt","w")) == NULL){
perror("");
exit(1);
}
sizeBuf1 = getChar(bufFile1, fp1); //geting the chars from file1
fclose(fp1);
sizeBuf1 = removingSPaces(bufFile1, sizeBuf1); //removing the \n if exists from chars of file1
sizeBuf2 = getChar(bufFile2, fp2); //geting the chars from file2
fclose(fp2);
sizeBuf2 = removingSPaces(bufFile2, sizeBuf2); //removing the \n if exists from chars of file2
maxSize = sizeBuf1 + sizeBuf2; //Max Size to loop for
orderChar(bufFile1, bufFile2, bufOut, maxSize, sizeBuf1, sizeBuf2); //Order the chars!
fprintf(fpOut, "%s", bufOut); //Printing to the file
fclose(fpOut);
/* COPIED FROM YOUR CODE */
char buf[64]={0}; //Just added the 0, because you cant initialize the array like with only {}
if((fpOut=fopen("fileOut.txt", "r")) == NULL){
perror("");
exit(1);
}
fgets(buf,64, fpOut);
if(!strncmp("aAbBcCdDeEfghijk", buf, 64))
printf("PASS\n");
else
printf("FAIL\n");
fclose(fpOut);
/* COPIED FROM YOUR CODE */
return 0;
}
Functions():
int removingSPaces(char array[MAX], int sizeArray){
int size = sizeArray;
if(array[sizeArray -1] == '\n'){
array[sizeArray -1] = '\0';
size = strlen(array);
}
return size;
}
int getChar(char buf[MAX], FILE *fp){
char bufAux[MAX];
int size;
while(fgets(bufAux, sizeof(bufAux), fp)){
size = strlen(bufAux);
}
strcpy(buf, bufAux);
return size;
}
void orderChar(char bufFile1[MAX], char bufFile2[MAX], char bufOut[MAX], int maxSize, int sizeBuf1, int sizeBuf2){
int positionsF1=0, positionsF2=0;
int aux = 0; //This will starts organization by the first file! If you want to change it just change to 1;
for(int i=0; i < maxSize; i++){
if(aux == 0 && positionsF1 != sizeBuf1){
bufOut[i]=bufFile1[positionsF1];
if(positionsF2!=sizeBuf2){
aux = 1;
}
positionsF1++;
}else if(aux == 1 && positionsF2 != sizeBuf2){
bufOut[i]=bufFile2[positionsF2];
if(positionsF1!=sizeBuf1){
aux = 0;
}
positionsF2++;
}
}
}
Content of file 1:
abcdefghijk
Content of file 2:
ABCDE

How to allocate memory for lines of a file in C?

I have created functions that are supposed to find the number of lines in a file (find_numlines()) and a function to read the lines of the file into char*** lines (read_lines()). The rest of the functions in my main were provided so the problems are not in those functions.
read_lines.c (UPDATED):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "read_lines.h"
int findnum_lines(FILE* fp){
int num_lines = 0;
int line;
line = getc(fp);
if (line != EOF) {
num_lines++;
do {
if (line == '\n') {
num_lines = num_lines + 1;
}
line = getc(fp);
}
while (line != EOF);
}
rewind(fp);
return num_lines;
}
void read_lines(FILE* fp, char*** lines, int* num_lines){
int i;
(*lines) = malloc(*num_lines * sizeof(char*));
for (i=0; i < *num_lines; i++)
{
(*lines)[i] = malloc(1000);
(*lines)[i][0] = '\0';
fgets((*lines)[i], 1000, fp);
}
}
main.c :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "read_lines.h"
void print_lines(char** lines, int num_lines){
int i;
for(i = 0 ; i < num_lines; ++i){
printf("%d. %s", i+1, lines[i]);
}
}
void free_lines(char** lines, int num_lines){
int i;
for(i = 0 ; i < num_lines; ++i){
free(lines[i]);
}
if(lines != NULL && num_lines > 0){
free(lines);
}
}
FILE* validate_input(int argc, char* argv[]){
FILE* fp = NULL;
if(argc < 2){
printf("Not enough arguments entered.\nEnding program.\n");
exit(0);
}
else if(argc > 2){
printf("Too many arguments entered.\nEnding program.\n");
exit(0);
}
fp = fopen(argv[1], "r");
if(fp == NULL){
perror("fopen");
printf("Unable to open file: %s\nEnding program.\n", argv[1]);
//fprintf(stderr, "Unable to open file %s: %s\n", argv[1], strerror(errno));
exit(0);
}
return fp;
}
int main(int argc, char* argv[]){
char** lines = NULL;
int num_lines = 0;
FILE* fp = validate_input(argc, argv);
num_lines = findnum_lines(fp);
read_lines(fp, &lines, &num_lines);
print_lines(lines, num_lines);
free_lines(lines, num_lines);
fclose(fp);
return 0;
}
read_lines.h :
#ifndef READ_LINES
#define READ_LINES
#include <stdio.h>
void read_lines(FILE* fp, char*** lines, int* num_lines);
int findnum_lines(FILE* fp);
#endif
Whenever I input a file the find_numlines() returns the correct number of lines but something goes wrong in the read_lines() because lines is still NULL.
The example file is normal.txt :
Hello Class
This is what I would call a normal file
It isn't very special
But it still is important
The ouptut should be:
1. Hello Class
2. This is what I would call a normal file
3. It isn't very special
4. But it still is important
In the following code I added the rewind command (mentioned by xing) and the memory allocation for each line and the "line table". Further improvements were performed in the code for counting the lines and the error handling.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int findnum_lines(FILE* fp){
int num_lines = 0;
int c;
c = getc(fp);
if (c != EOF) {
num_lines++;
do {
if (c == '\n') {
num_lines = num_lines + 1;
}
c = getc(fp);
}
while (c != EOF);
}
rewind(fp);
return num_lines;
}
void read_lines(FILE* fp, char*** lines, int* num_lines){
int i;
// allocate memory for pointers to start of lines
(*lines) = malloc(*num_lines * sizeof(char*));
for (i=0; i < *num_lines; i++)
{
(*lines)[i] = malloc(1000);
(*lines)[i][0] = '\0'; // terminate for the case that last line does not contain characters
fgets((*lines)[i], 1000, fp); // read up to 999 characters and terminate string
}
}
void print_lines(char** lines, int num_lines){
int i;
for(i = 0 ; i < num_lines; ++i){
printf("%d. %s", i+1, lines[i]);
}
printf("\n");
}
void free_lines(char** lines, int num_lines){
int i;
for (i = 0 ; i < num_lines; ++i) {
if (lines[i]!=NULL) {
free(lines[i]);
}
}
if (lines != NULL){
free(lines);
}
}
FILE* validate_input(int argc, char* argv[]){
FILE* fp = NULL;
if (argc < 2){
printf("Not enough arguments entered.\n");
}
else if (argc > 2){
printf("Too many arguments entered.\n");
}
else {
fp = fopen(argv[1], "r");
if (fp == NULL){
printf("Unable to open file: %s\n", argv[1]);
}
}
return fp;
}
int main(int argc, char* argv[]){
char** lines = NULL;
int num_lines = 0;
FILE* fp = validate_input(argc, argv);
if (fp != NULL)
{
num_lines = findnum_lines(fp);
read_lines(fp, &lines, &num_lines);
print_lines(lines, num_lines);
free_lines(lines, num_lines);
fclose(fp);
}
return 0;
}

How to split a text file into multiple parts in c

What i need to do, is to take a file of n lines, and for every x lines, create a new file with the lines of the original file. An example would be this:
Original File:
stefano
angela
giuseppe
lucrezia
In this case, if x == 2, 3 file would be created, in order:
First file:
stefano
angela
Second FIle:
giuseppe
lucrezia
Third File:
lorenzo
What i've done so far is this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 10
int getlines(FILE *fp)
{
int c = 0;
int ch;
do{
ch = fgetc(fp);
if(ch == '\n')
{
c++;
}
}while(ch != EOF);
fseek(fp, 0 , SEEK_SET);
return c;
}
int ix = 0;
void Split(FILE *fp, FILE **fpo, int step, int lines, int *mem)
{
FILE **fpo2 = NULL;
char * filename = malloc(sizeof(char)*64);
char * ext = ".txt";
char number[2];
for(int i = ix; i < *mem; i++)
{
itoa(i+1, number,10);
strcpy(filename, "temp");
strcat(filename, number);
strcat(filename, ext);
if(!(fpo[i] = fopen(filename, "w")))
{
fprintf(stderr, "Error in writing\n");
exit(EXIT_FAILURE);
}
}
char ch;
int c = 0;
do{
ch = fgetc(fp);
printf("%c", ch);
if(ch == '\n')
{
c++;
}
if(c >= step)
{
c = 0;
ix++;
if(ix >= *mem && (ix*step) <= lines)
{
*mem = *mem + 1;
fpo2 = realloc(fpo, sizeof(FILE*)*(*mem));
Split(fp, fpo2, step, lines, mem);
}
}
putc(ch, fpo[ix]);
}while(ch != EOF);
}
int main()
{
FILE * fp;
if(!(fp = fopen("file.txt", "r")))
{
fprintf(stderr, "Error in opening file\n");
exit(EXIT_FAILURE);
}
int mem = N;
int lines = getlines(fp);
int step = lines/N;
FILE **fpo = malloc(sizeof(FILE *)*N);
Split(fp, fpo, step, lines, &mem);
exit(EXIT_SUCCESS);
}
I'm stack with segmentation error, i couldn't find the bug doing
gdb myprogram
run
bt
I really appreciate any help.
EDIT:
I've changed some things and now it works, but it creates an additional file that contains strange characters. I need to still adjust some things:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 10
int getlines(FILE *fp)
{
int c = 0;
int ch;
do{
ch = fgetc(fp);
if(ch == '\n')
{
c++;
}
}while(ch != EOF);
fseek(fp, 0 , SEEK_SET);
return c;
}
int ix = 0;
void Split(FILE *fp, FILE **fpo, int step, int lines, int *mem)
{
FILE **fpo2 = NULL;
char * ext = ".txt";
for(int i = ix; i < *mem; i++)
{
char * filename = malloc(sizeof(char)*64);
char * number = malloc(sizeof(char)*64);
itoa(i+1, number,10);
strcpy(filename, "temp");
strcat(filename, number);
strcat(filename, ext);
if(!(fpo[i] = fopen(filename, "w")))
{
fprintf(stderr, "Error in writing\n");
exit(EXIT_FAILURE);
}
free(number);
free(filename);
}
char ch;
int c = 0;
do{
ch = fgetc(fp);
printf("%c", ch);
if(ch == '\n')
{
c++;
}
if(c >= step)
{
c = 0;
ix++;
if(ix >= *mem && ((ix-1)*step) <= lines)
{
*mem = *mem + 1;
fpo2 = realloc(fpo, sizeof(FILE*)*(*mem));
Split(fp, fpo2, step, lines, mem);
}
}
putc(ch, fpo[ix]);
}while(ch != EOF);
}
int main()
{
FILE * fp;
if(!(fp = fopen("file.txt", "r")))
{
fprintf(stderr, "Error in opening file\n");
exit(EXIT_FAILURE);
}
int mem = N;
int lines = getlines(fp);
int step = lines/N;
FILE **fpo = malloc(sizeof(FILE *)*N);
Split(fp, fpo, step, lines, &mem);
exit(EXIT_SUCCESS);
}
There are a few problems in your code. But first I think you need to fix the most important thing
int step = lines/N;
Here step is 0 if your input file has less than N lines of text. This is because lines and N both are integer and integer division is rounding down.
I won't fix your code, but I'll help you with it. Some changes I
suggest:
Instead of getlines, use getline(3) from the standard
library.
fseek(fp, 0 , SEEK_SET) is pointless.
In char * filename = malloc(sizeof(char)*64), note that
both arguments to malloc are constant, and the size is arbitrary.
These days, it's safe to allocate filename buffers statically,
either on the stack or with static: char filename[PATH_MAX].
You'll want to use limits.h to get that constant.
Similarly you have no need to dynamically allocate your FILE
pointers.
Instead of
itoa(i+1, number,10);
strcpy(filename, "temp");
strcat(filename, number);
strcat(filename, ext);
use sprintf(filename, "temp%d%s", i+1, ext)
get familiar with err(3) and friends, for your own convenience.
Finally, your recursive Split is -- how shall we say it? -- a nightmare. Your whole program
should be something like:
open input
while getline input
if nlines % N == 0
create output filename with 1 + n/N
open output
write output
nlines++

Most common letter on a file (C programming)

I need to create a function that finds the most common letter in a file using C.
Can't figure out my problem, for some reason it always returns [.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
char commonestLetter(char* filename);
void main()
{
char str[101], ch;
FILE *fout;
fout = fopen("text.txt", "w");
if (fout == NULL)
{
printf("Can't open file\nIt's probably your fault, worked perfectly on my PC ;)\n");
fclose(fout);
}
printf("Enter string (to be written on file)\n");
gets(str);
fputs(str, fout);
ch = commonestLetter("text.txt");
printf("The most common letter is %c\n", ch);
fclose(fout);
}
char commonestLetter(char* filename)
{
char ch;
int i, count[26];
int max = 0, location;
FILE *f = fopen(filename, "r");
if (f == NULL)
{
printf("file is not open\n");
return;
}
for (i = 0; i < 26; i++)
count[i] = 0;
while ((ch = fgetc(f)) != EOF)
{
if (isalpha(ch))
count[toupper(ch) - 'A']++;
}
for (i = 0; i < 26; i++)
{
if (count[i] >= max)
{
max = count[i];
location = i + 1;
}
}
return location + 'A';
}
Do
location=i;
No need of i+1
As you are doing location+'A';
Suppose the location count[25] has the highest count, so the location becomes 25+1=26.
Now the return will be 26+65=91 which is of '['
The code of yours is slightly modified but the logic of your is kept
#include <stdio.h>
#include <string.h>
#include <ctype.h>
char commonestLetter(char* filename);
int main()
{
char str[101], ch;
FILE *fout;
fout = fopen("text.txt", "w");
if (fout == NULL)
{
printf("Can't open file\nIt's probably your fault, worked perfectly on my PC ;)\n");
return 0;
}
printf("Enter string (to be written on file): ");
fgets(str,sizeof(str),stdin);
fputs(str, fout);
fclose(fout);
ch = commonestLetter("text.txt");
printf("The most common letter is %c\n", ch);
return 0;
}
char commonestLetter(char* filename)
{
char ch;
int i, count[26];
int max = 0, location;
FILE *f = fopen(filename, "r");
if (f == NULL)
{
printf("file is not open\n");
return;
}
memset(&count,0,sizeof(count));
while ((ch = fgetc(f)) != EOF)
{
if (isalpha(ch))
count[toupper(ch) - 'A']++;
}
for (i = 0; i < 26; i++)
{
if (count[i] >= max)
{
max = count[i];
location = i;
}
}
fclose(f);
return location + 'A';
}
Input & Output:
Enter string (to be written on file): Gil this is a testing
The most common letter is I
The problem here is, in your code,
location = i + 1;
location is i+1 at the end, and you're returning location + 'A'; which is (because of your input, probably) (25+1) + 'A' , i.e., 26 + 'A' which is [.

Unexpected Segfault - What am I doing wrong

I've been trying to blow the cobwebs off my C programming skills, and I've been getting an error I can't seem to figure out. This program reads in a list of integers separated by newlines. This bit happens in read_integer_file... I have no issues going through the input there. It's when I pass the data back to main via out that I have the problem.
#include <stdlib.h>
#include <stdio.h>
int read_integer_file(char* filename, int* out)
{
FILE* file;
file = fopen(filename, "r");
/* check if the file open was successful */
if(file == NULL)
{
return 0;
}
int num_lines = 0;
/* first check how many lines there are in the file */
while(!feof(file))
{
fscanf(file, "%i\n");
num_lines++;
}
/* seek to the beginning of the file*/
rewind(file);
out = malloc(sizeof(int)*num_lines);
if(out == NULL)
return 0;
int inp = 0;
int i = 0;
while(!feof(file))
{
fscanf(file, "%i\n", &inp);
out[i] = inp;
printf("%i\n", out[i]); /* <---- Prints fine here! */
i++;
}
return num_lines;
}
int main(int argc, char** argv)
{
if(argc < 2)
{
printf("Not enough arguments!");
return -1;
}
/* get the input filename from the command line */
char* array_filename = argv[1];
int* numbers = NULL;
int number_count = read_integer_file(array_filename, numbers);
for(int i = 0; i < number_count; i++)
{
/* Segfault HERE */
printf("%i\n", numbers[i]);
}
}
You have not allocated any memory for numbers. Currently it is pointing to no where. When it gets back to the calling function it is still pointed to nowhere. Pass a pointer to a pointer to the function to allocate it within the function.
int read_integer_file(char* filename, int** out)
{
...
*out = malloc(sizeof(int)*num_lines);
...
int number_count = read_integer_file(array_filename, &numbers);
This is a version of your code working.. Keep in mind also that fscanf just skip the \n the way you wrote it so it's like writing fscanf(file, "%d");
And if you don't put a variable to handle what it reads the compiler may not see it but you'll probably get an error..
So here is the code :
#include <stdlib.h>
#include <stdio.h>
int read_integer_file(char* filename, int **out)
{
FILE* file;
file = fopen(filename, "r");
/* check if the file open was successful */
if(file == NULL)
{
return 0;
}
int num_lines = 0;
int garbi;
char garbc;
/* first check how many lines there are in the file */
while(!feof(file))
{
fscanf(file, "%d", &garbi);
fscanf(file, "%c", &garbc);
if (garbc=='\n') ++num_lines;
}
/* seek to the beginning of the file*/
rewind(file);
int *nbr = malloc(sizeof(int)*num_lines);
if(nbr == NULL)
return 0;
int i = 0;
while(!feof(file))
{
fscanf(file, "%d", &nbr[i++]);
fscanf(file, "%c", &garbc);
}
*out=nbr;
return num_lines;
}
int main(int argc, char** argv)
{
if(argc < 2)
{
printf("Not enough arguments!");
return -1;
}
/* get the input filename from the command line */
char* array_filename = argv[1];
int *numbers = NULL;
int number_count = read_integer_file(array_filename, &numbers);
int i;
for(i = 0; i < number_count; ++i)
printf("%d\n", numbers[i]);
return 0;
}

Resources