I have a function which open a file, read its content line by line and then push it to an array. I have managed to get the array functionnal inside the right function, but when I want to get it back to my main function, I cannot get any items of my array.
Some code will help you to understand:
My main function:
/* ----------------- MAIN ------------ */
int main(int argc, char *argv[]) {
/*... some useless code for now ... */
char **ptrLines = NULL;
ptrLines = readEventFile(ptrParam, ptrLines);
outputExecTrace(WAR, "PTRLINES x : %x", ptrLines);
outputExecTrace(WAR, "PTRLINES char[] : %s", *(ptrLines + 2));
return EXIT_SUCCESS;
}
My fileReader function:
char** readEventFile(Parameters *parameters, char **arrLine) {
FILE *fp = fopen(parameters->inputFilePath, "r");
if (fp == NULL)
exit(0);
char line[128];
int nbCharOfLine = 0;
while(1) {
fgets(line, sizeof(line), fp);
if (feof(fp))
break;
nbCharOfLine++;
}
fclose(fp);
arrLine = malloc(sizeof(line) * nbCharOfLine);
nbCharOfLine = 0;
fp = fopen(parameters->inputFilePath, "r");
while(1) {
fgets(line, sizeof(line), fp);
if (line[0] != '#') {
arrLine[nbCharOfLine] = malloc((strlen(line)+1) * sizeof(char));
strcpy(arrLine[nbCharOfLine], line);
nbCharOfLine++;
}
if (feof(fp))
break;
}
fclose(fp);
outputExecTrace(WAR, "ARRLINE x : %x", arrLine);
outputExecTrace(WAR, "ARRLINE char[] : %s", *(arrLine + 2));
return arrLine;
}
Has it is, my outputs are the followings:
WARNING: ARRLINE int : -2020552688
WARNING: ARRLINE char[] : 1 3 4 //This is the result I am looking for.
WARNING: PTRLINES int : -2020552688 // Same as ARRLINE
Segmentation fault (core dumped) // And this is because ptrLines[2] doesn't contains anything... but why ?!
How can I fix this ?
It's hard to tell exactly what happen, because you have several small problems within code, which could lead to this, try to change your code in following way:
char** readEventFile(char* fileName) {
char line[128];
int nbCharOfLine = 0;
FILE *fp = fopen(fileName, "r");
if (fp == NULL)
exit(1);
while (!feof(fp)) {
char *r = fgets(line, sizeof(line), fp); // NOTE: proper handling of fgets return value
if ((r != NULL) && (line[0] != '#'))
nbCharOfLine++;
}
fclose(fp);
char **arrLine = calloc(nbCharOfLine, sizeof(char*)); // use calloc to be sure
nbCharOfLine = 0;
fp = fopen(fileName, "r");
while (!feof(fp)) {
char *r = fgets(line, sizeof(line), fp);
if ((r != NULL) && (line[0] != '#')) {
arrLine[nbCharOfLine] = calloc(strlen(line) + 1, sizeof(char));
strcpy(arrLine[nbCharOfLine++], line);
}
}
fclose(fp);
return arrLine;
}
in your main, you will call this function like:
char **ptrLines = readEventFile(ptrParam->inputFilePath);
Not so sure this is the whole problem, but the posted code:
while(1) {
fgets(line, sizeof(line), fp);
if (line[0] != '#') {
arrLine[nbCharOfLine] = malloc((strlen(line)+1) * sizeof(char));
strcpy(arrLine[nbCharOfLine], line);
nbCharOfLine++;
}
if (feof(fp))
break;
}
is not the right approach for several reasons,
including that function feof()
is only asserted 'true' when the code has tried to read past the
end of the file.
suggest:
while( fgets(line, sizeof(line), fp) )
{
if (line[0] != '#')
{
if( NULL == (arrLine[nbCharOfLine] = malloc((strlen(line)+1) * sizeof(char)) ) )
{ // then, malloc failed
perror( "malloc failed" );
// close file and free all malloc'd areas
exit( EXIT_FAILURE );
}
// implied else, malloc successful
strcpy(arrLine[nbCharOfLine], line);
nbCharOfLine++;
}
}
Related
I am trying to implement the function that compares two files. The function should restore the first lines that differ from each other. If the files are the same, NULL will be returned. The function ends as soon as either of the files ends, and then NULL is returned. I think my if functions doesn't work and so on this function don't return the lines.
Here is my code:
char *difference(const char* file1, const char* file2)
{
char line1[1000];
char line2[1000];
char *a = malloc(1000 * sizeof(char));
FILE *f1 = fopen(file1, "r");
FILE *f2 = fopen(file2, "r");
if (!f1 || !f2) // checking if there is any error
{
return -1;
}
while (fgets(line1, sizeof(line1), file1) != NULL && fgets(line2, sizeof(line2), file1) != NULL)
{
if (strcmp(line1, line2) != 0)
{
strcpy(a, line1);
strcpy(a, line2);
}
else
{
return NULL;
}
}
fclose(f1);
fclose(f2);
return a;
int main(void)
char* diff = difference("testifile.c", "testifile2.c");
printf("\n--- Difference:\n");
printf("%s", diff);
free(diff);
return 0;
}
Yeah that doesn't work so good. Here are the bugs:
return -1;
Does not compile. Did you mean
return (char*)-1;
Also, leaks memory. Do:
if (f1) fclose(f1);
if (f2) fclose(f2);
return (char*)-1;
Oops you read from file1 twice:
while (fgets(line1, sizeof(line1), file1) != NULL && fgets(line2, sizeof(line2), file1) != NULL)
should be
while (fgets(line1, sizeof(line1), file1) != NULL && fgets(line2, sizeof(line2), file2) != NULL)
Memory trashing:
line3=strcat(line1,line2);
Should be:
strcat(strcpy(a,line1),line2);
Only ever checks first line because early return:
else
{
return NULL;
}
Just eliminate that block.
Oops forgot to check for errors:
char* diff = difference("testifile.c", "testifile2.c");
char* diff = difference("testifile.c", "testifile2.c");
if (diff == (char *)-1) {
/* handle file open error */
}
else if (diff == NULL) {
/* handle no difference */
}
else {
/* your message */
free(diff);
}
I have a practice question in C that asks me to create a function that only copies part of a file to another one. The restrictions are that lines with greater than maxlen characters are not copied to the new file, and the newline character does not count, so it should not be copied. Part of my function says that if a file does not exist, it should explicitly say so, and I am getting those error messages when I run that code; however, I can see that the files are created are inside my folder. Whenever I open the file I'm trying to read after running the code, I get this:
./Debug/main.c.o ./Debug/dot.c.o ./Debug/dataBase.c.o ./Debug/intPrompt.c.o ./Debug/numWords.c.o ./Debug/LinkedList.c.o
Below is my code :
void shortLines(char* f1, char* f2, int maxlen) {
FILE* fp = fopen(f1, "r");
FILE* fp2 = fopen(f2, "w");
if (fp == NULL) {
perror("File does not exist");
}
if (fp2 == NULL) {
perror("File does not exist");
}
char singleLine[maxlen];
char check;
size_t len;
do {
fgets(singleLine, maxlen, fp);
len = strlen(singleLine);
if (singleLine[len-1] == '\n') {
singleLine[len-1] = '\0';
}
fprintf(fp2, "%s", singleLine);
} while ((check=getc(fp) != EOF));
}
int main(int argc, char **argv) {
shortLines("Andrew.txt", "Andrew2.txt", 25);
return 0;
}
I just made new files called Andrew.txt and Andrew2.txt and these ones seem to be working for some strange reason. Regardless, there were a few problems in the code. First of all, after fgets is called, I needed to make sure to flush out the remaining characters in the line. I do this with a while loop and fgetc. If I reach an EOF, then I continue, and then fgets also returns an EOF, thus breaking the outer loop.
void shortLines(char* f1, char* f2, int maxlen) {
FILE* fp = fopen(f1, "r");
FILE* fp2 = fopen(f2, "w");
if (fp == NULL) {
perror(f1);
}
if (fp2 == NULL) {
perror(f2);
}
char line[maxlen+1];
size_t len;
char c;
while (fgets(line, maxlen+1, fp) != NULL) {
len = strlen(line);
if (len == maxlen) {
while ((c=fgetc(fp)) != '\n') {
if (feof(fp)) {
break;
}
}
continue;
}
if (line[len-1] == '\n') {
line[len-1] = '\0';
}
fprintf(fp2, "%s\n", line);
}
}
I am creating a program which copies text file data from one file and changes its case to lower or upper on choice, but when I execute the program I receive the following result and the text case is not changed or copied.
#include <stdio.h>
int main() {
FILE *fp = NULL;
FILE *fp2 = NULL;
char str[200];
char var;
int i;
char copy;
fp = fopen("file1.txt", "a");
fp2 = fopen("file2.txt", "w");
printf("Enter choice: ");
scanf(" %c", &var);
if (fp != NULL && var == 'L') {
while ( fgets(str, 200, fp) != NULL ) {
putchar(tolower(fp[i]));
i++;
}
puts(str);
}
else if (fp != NULL && var == 'U') {
while ( fgets(str, 200, fp) != NULL ) {
putchar(toupper(fp[i]));
i++;
}
puts(str);
}
else {
printf("ERROR: No proper choice was made \n");
}
while (1) {
copy = fgetc(fp);
if (copy == EOF) {
break;
}
else {
putc(copy , fp2);
}
}
return 0;
fclose(fp);
fclose(fp2);
}
The output I get is:
Enter choice: U
▒▒
putchar(tolower(fp[i])); should have generated compiler warnings. Insure the compiler warning are all enabled or consider a new compiler.
Replace in 2 places, both upper and lower section.
while ( fgets(str, 200, fp) != NULL ) {
putchar(tolower(fp[i]));
i++;
}
// With to iterate over each character
while (fgets(str, sizeof str, fp) != NULL) {
for (i=0; str[i]; i++) {
putchar(tolower(str[i]));
}
}
Change to int to properly distinguish all characters returned from fgetc() from EOF.
Open with "r" to read from the beginning of the file
// fp = fopen("file1.txt", "a")
fp = fopen("file1.txt", "r");
The problem is that you use fgets, which reads a string from the file. A better way of doing this would be to use fgetc, which reads just one character at a time and process it appropiately.
I'm just getting into C and I figured this would be a good exercise. I've been putsing around with fgets trying to read from a file and I am just doing something wrong. I would like to enter the file name to read, enter the file name to output to, create that file, sort it (just a list of words), and then dump the sorted list into the created file. I know I should be doing something like:
char strIn[25];
printf("Enter a source filename: ");
fgets(strIn, 25, stdin);
printf("You entered: %s \n", strIn);
FILE *infile;
infile = fopen(strIn, "r");
if (infile == NULL){
printf("Unable to open file.");
}
char strOut[25];
printf("Enter a destination filename: ");
fgets(strOut, 25, stdin);
printf("You entered: %s \n", strOut);
FILE *outfile;
Any help is appreciated! Thank you
fgets puts the newline character \n at the end of your buffer. So you need to remove it.
int length = strlen(strIn);
if ( length > 0 && strIn[length-1] == '\n' )
strIn[length-1] = '\0';
You are on the right track. qsort will do what you want. The approach used here is not scalable; everything is held in memory and static allocation will make things HUGE very quickly, but it works as a toy example. At the moment it will break once there are more than 1000 lines in the input file.
# include <stdio.h>
# include <string.h>
#define MAXNAMELEN 100
#define MAXLINELEN 100
#define MAXITEMS 1000
int main(int argc, char ** argv) {
FILE * infile, * outfile;
// Statically allocated -- dastardly!
char name[MAXNAMELEN];
char line[MAXLINELEN];
char lines[MAXITEMS][MAXLINELEN];
int i, items = 0;
printf("Enter a source filename: ");
fgets(name, sizeof(name), stdin);
name[strlen(name)-1] = '\0'; // strip newline
// No error checking -- ANYWHERE -- dastardly!
infile = fopen(name, "r");
while (fgets(line, sizeof(line), infile)) {
strcpy(lines[items], line);
items++;
}
qsort(lines, items, MAXLINELEN, strcmp);
printf("Enter a destination filename: ");
fgets(name, sizeof(name), stdin);
name[strlen(name)-1] = '\0'; // strip newline
outfile = fopen(name, "w");
for (i=0; i<items; i++) {
fputs(lines[i], outfile);
}
fclose(infile);
fclose(outfile);
}
Now with dynamic allocation and error-checking (possibly an improvement on than the version above). Sorts /usr/share/dict/words (99171 lines) no problem at all. Still requires that the entire array be held in memory. See External Sorting for a way around that.
# include <stdio.h>
# include <string.h>
# include <stdlib.h>
#define CHUNKLEN 100
#define INITITEMS 1000
/* Reads a string from stream into buffer until a newline or EOF.
buffer is dynamically allocated (and reallocated if necessary)
to ensure the string fits. Returns the number of characters put
into the buffer (zero if EOF and no characters read), or -1 on error. */
int unlimited_read(char ** buffer, FILE * stream) {
int bufl = CHUNKLEN;
int strl = 0;
char * chunk = (char *)malloc(CHUNKLEN);
if ( (*buffer = (char *) malloc(CHUNKLEN)) == NULL ) {
perror("memory error (malloc)");
return -1;
}
while (fgets(chunk, CHUNKLEN, stream) != NULL) {
strcpy(*buffer + strl, chunk);
strl += strlen(chunk);
if ( (strl == bufl - 1 ) && *(*buffer + strl - 1) != '\n') {
// lengthen buffer
bufl += CHUNKLEN - 1;
if ( (*buffer = realloc(*buffer, bufl)) == NULL ) {
perror("memory error (realloc)");
return -1;
}
} else {
// This shouldn't fail -- we're only ever making it smaller
*buffer = realloc(*buffer, strl);
return strl;
}
} // while
// If fgets returned NULL and we are not at EOF, it didn't work
return feof(stream) ? strl : -1;
}
/* Compare two strings given pointers to those strings.
Routine is courtesy of the qsort man page */
int cmpstringp(const void *p1, const void *p2) {
return strcmp(* (char * const *) p1, * (char * const *) p2);
}
/* Sort lines in a file. File must end with a newline. */
int main(int argc, char ** argv) {
FILE * infile, * outfile;
char * inname, * outname, *tmpstr;
char ** lines;
int ret, tmp, nlines, i, items = 0;
if (argc != 3) {
printf("Usage: %s file_to_sort output_file\n", argv[0]);
exit(EXIT_FAILURE);
}
inname = argv[1];
outname = argv[2];
if ( (lines = malloc(INITITEMS * sizeof(char *))) == NULL) {
perror("memory error (malloc)");
exit(EXIT_FAILURE);
}
nlines = INITITEMS;
infile = fopen(inname, "r");
while ((ret = unlimited_read(&lines[items], infile)) > 0) {
items++;
if (items == nlines) {
nlines += INITITEMS;
lines = realloc(lines, (nlines * sizeof(char *)));
}
}
if (ret < 0) {
printf("WARNING: possibly truncated file\n");
}
tmpstr = lines[items - 1]; // Final line in file
tmp = strlen(tmpstr);
if (tmpstr[tmp - 1] != '\n') {
printf("Error: input file does not end with newline\n");
exit(EXIT_FAILURE);
}
qsort(lines, items, sizeof(char *), cmpstringp);
outfile = fopen(outname, "w");
for (i = 0; i < items; i++) {
fputs(lines[i], outfile);
free(lines[i]);
}
free(lines);
fclose(infile);
fclose(outfile);
}
I've been at this for hours now and I feel like I'm not getting some fundamental techniques in C. I've been trying to read in a specific line and store it into 2 separate files from one file. The source file (temp) is the one I'm reading in and the 2 files, data and text are the 2 files I'm trying to store.
TL;DR, how do I split up contents from a file into two separate file?
For example, the input file is:
.data
A: .word 32
B: .word 16
.text
main:
la $s0 A
lw $s0 0($s0)
la $s1 B
lw $s1 0($s1)
This function will take in the temp file and process the .data and .text segments into separate files.
void process_file(FILE * temp)
{
FILE * data, * text;
char * token;
char * nextLine;
char line[256];
char * str_token = malloc(256 * sizeof(char));
char * str = malloc(256 * sizeof(char));
int i;
data = fopen("data.asm", "w");
text = fopen("text.asm", "w");
if (temp == NULL || data == NULL || text == NULL)
{
printf("UNABLE TO OPEN OR LOCATE FILES. EXITING.\n");
exit(1);
}
while (!feof(temp))
{
if ((nextLine = fgets(line, 256, temp)) != NULL)
{
token = strtok(nextLine, "\n");
//printf("%s", nextLine);
if (token != NULL)
{
strcat(str_token, token);
token = strtok(NULL, "\n");
if ((strstr(str_token, ".data")) != NULL)
{
strcat(str, str_token);
fprintf(data, "%s", str); //ADDING THIS CAUSES A SEG FAULT :(
}
else if ((strstr(token, ".text")) != NULL)
{
fprintf(text, "%s", token);
token = strtok(NULL, "\n");
}
}
}
}
}
Thanks!
void process_file(FILE *temp){
FILE *data, *text, *fp;
char line[256], str[256];
char *token;
data = fopen("data.asm", "w");
text = fopen("text.asm", "w");
if (temp == NULL || data == NULL || text == NULL) {
printf("UNABLE TO OPEN OR LOCATE FILES. EXITING.\n");
exit(1);
}
fp = data;//default for not start with .data and .text
while(fgets(line, sizeof line, temp)){
strcpy(str, line);
if((token=strtok(str, " \t\n"))!=NULL){//not blank line
if(strcmp(token, ".data")==0)
fp = data;
else if(strcmp(token, ".text")==0)
fp = text;
}
fprintf(fp, "%s", line);
}
fclose(data);
fclose(text);
}
This is what I used to get your answer, using the code you provided anyway
void process_file(FILE * temp)
{
//You may use NULL versus 0
FILE * data = 0, * text = 0;
char * token = 0;
char * nextLine = 0;
char line[256];
int i = 0;
data = fopen("data.asm", "w");
text = fopen("text.asm", "w");
if ( 0 == temp || 0 == data || 0 == text )
{
printf("UNABLE TO OPEN OR LOCATE FILES. EXITING.\n");
exit(1);
}
while (!feof(temp))
{
if ((nextLine = fgets(line, 256, temp)) != NULL)
{
token = strtok(nextLine, "\n");
//printf("%s", nextLine);
if (0 != token){
if(strcmp(token, ".data") == 0 ){
//Make use of that i
i = 1;
}
else if(strcmp(token, ".text") == 0){
i = 2;
}
switch(i){
case 1:
fprintf(data, "%s\r\n", token);
break;
case 2:
fprintf(text, "%s\r\n", token);
break;
default:
printf("Invalid!");
break;
}
}
}
}
fclose(data);
fclose(text);
fclose(temp);
}
#include <string.h>
#include <stdio.h>
void process_file(FILE * temp)
{
FILE * data, * text, *write = NULL;
char * token;
char * nextLine;
char line[256];
char * str_token = malloc(256 * sizeof(char));
char * str = malloc(256 * sizeof(char));
char val [] = "safasfsdf";
int i;
data = fopen("data.asm", "w");
text = fopen("text.asm", "w");
if (temp == NULL || data == NULL || text == NULL)
{
printf("UNABLE TO OPEN OR LOCATE FILES. EXITING.\n");
exit(1);
}
while (!feof(temp))
{
if ((nextLine = fgets(line, 256, temp)) != NULL)
{
if ((strstr(line, ".data")) != NULL)
{
write = data;
}
else if ((strstr(line, ".text")) != NULL)
{
write = text;
}
if(line[0]!= '\n'){
printf ("%p %s",write, line);
fprintf(write, "%s", line);
}
}
}
fclose (data);
fclose (text);
}
pattern is identified first. Based on the pattern file pointer is selected. I have removed the few unwanted line from the original source and make it simple. Hope this will be helpful to you.