fopen reading Invalid argument C - c

I can't seem to find an answer to the fopen issue. It seems to be common, but everything I'm trying is not working, from what I have read this seems to be caused by a trailing newline, but I'm not sure:
The aim is to move from the hardcoded filename (which is commented) to the command line input for the file name
any help would be much appreciated
My code
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main( int argc, char *argv[] )
{
setbuf(stdout, NULL);
struct Person { char lname[20]; char fname[20]; int id; };
int N1, i ;
struct Person *p;
// char filename[] = "../src/students.csv" ;
//
// FILE *str = fopen( filename, "r") ;
// if (str==NULL) {
// perror(filename) ;
// exit(-1) ;
// }
printf("Please input file name:"); // Asks user to enter file name.
FILE *str2 = fopen(argv[1], " r"); // File opened for reading
printf("%p", str2);
if (str2 == NULL) { // If issue opening file display the error.
perror(argv[1]);
exit(-1);
}
fscanf( str2, "%d\n", &N1 ) ;
p = (struct Person*)calloc( N1 , sizeof(struct Person) ) ;
if (p==NULL) {
fprintf(stderr, "Can't allocate %d structs -- exiting.\n", N1 ) ;
exit(-1) ;
}
for ( i=0 ; i<N1 ; i++ ) {
fscanf( str2, " %[^,],%[^,],B%d", p[i].lname, p[i].fname, &(p[i].id) );
}
fclose(str2) ;
/* Access the array... Just like a static array */
printf("%s, %s, B000%d\n", p[4].lname, p[4].fname, p[4].id) ;
free(p) ;
return 0;
}
studnets.csv

Related

Function that copies parts of a file to another in C

I have to make a function which reads a file line by line and copies a some of them to another file. The head of the function has to look like this: "int write_x(const char *input_path, const char *output_path, int x)" and can't be changed. For example if x = 3 every third line of the input txt-file should be copied to the output txt-file. Every line has a maximum of 80 signs. I hope someone can help me because i'm not programming very long yet.
This is what I have alreaday, but it doesn't work:
#include <stdlib.h>
#include <stdio.h>
int write_x(const char *input_path, const char *output_path, int x){
input_path = "in.txt";
output_path = "out.txt";
FILE *in
FILE *out
char text[100];
for(int i = 0; i < 100; i++){
fgets(text[i], 80, in);
if(i % x == 0) {
fprintf(out, "%s\n", text[i]);
}
}
return 0;
}
I didn't compile it (I'll leave that to you), but how about something like this?
Note that if your teacher penalizes for the use of 'goto', then you'll need to modify the error handling.
#include <stdio.h>
#include <stdlib.h>
int write_x(const char *input_path, const char *output_path, int x) {
int result = 0 ;
FILE * inputFile=NULL;
FILE * outputFile=NULL;
/* Open the input file for reading */
inputFile = fopen( input_path, "r" ) ;
if ( inputFile == NULL ) {
perror( "fopen(input_path)" ) ;
result = -1;
goto clean_up;
}
/* Open the output file for writing */
outputFile = fopen( output_path, "w") ;
if ( outputFile == NULL ) {
perror( "fopen(output_path)" ) ;
result = -1;
goto clean_up;
}
int lineNumber = 0 ;
char * lineBuffer = NULL ; // memory will be allocated by getline()... but you'll need to free it up afterwards
int lenBuffer ; // getline will set how bug the buffer is
/* Repeat for each line read */
while (getline( &lineBuffer, &lenBuffer, inputFile) != -1) {
/* Only at each 'x' line count */
if ( (++lineNumber % x ) == 0 ) {
/* Write the line to the output file */
if ( fwrite( lineBuffer, lenBuffer, 1, outputFile ) != lenBuffer ) {
perror("fwrite");
result = -1;
goto clean_up;
}
}
}
clean_up:
/* avoid memory leak */
if ( lineBuffer != NULL ) {
free( lineBuffer ) ;
}
/* Close the input file */
if ( inputFile != NULL ) {
fclose( inputFile ) ;
}
/* Close the output file */
if ( outputFile != NULL ) {
fclose( outputFile ) ;
}
/* All done */
return result ;
}
It seems like a really bad design to be passing paths to this function as arguments instead of FILE *'s, but you're under no obligation to read the file line by line. Just read one character at a time. Something like:
#include <stdlib.h>
#include <stdio.h>
FILE * xfopen(const char *path, const char *mode);
int
write_x(const char *input_path, const char *output_path, int x)
{
FILE *in = xfopen(input_path, "r");
FILE *out = xfopen(output_path, "w");
int c;
int count = 1;
while( (c = fgetc(in)) != EOF ){
if( count == x ){
fputc(c, out);
}
if( c == '\n' ){
count = ( count % x ) + 1;
}
}
return 0;
}
int
main(int argc, char **argv)
{
int step = argc > 1 ? strtol(argv[1], NULL, 10) : 1;
char *in = argc > 2 ? argv[2] : "in.txt";
char *out = argc > 3 ? argv[3] : "out.txt";
write_x(in, out, step);
return 0;
}
FILE *
xfopen(const char *path, const char *mode)
{
FILE *fp = path[0] != '-' || path[1] != '\0' ? fopen(path, mode) :
*mode == 'r' ? stdin : stdout;
if( fp == NULL ){
perror(path);
exit(EXIT_FAILURE);
}
return fp;
}

How to parse table from txt file in C variables?

I have a text file in this format:
#Name #Company #ID
Name1 Brand1 1234
Name2 Brand2 5678
And a struct:
struct MyStruct{
char name[TEXT_LEN];
char company[TEXT_LEN];
char ID[TEXT_LEN];
};
typedef struct MyStruct Data_t;
What I want... is to load the data from text file in appropriate variables. It should ignore first line because those are headers...
This is what I've been trying so far but without success:
int loadDataFromFile(Data_t *items, long len, char *inputFile)
{
FILE *fp;
if ((fp = fopen(inputFile, "r")))
{
for (long i = 0; i < len; i++)
{
/*fscanf(fp, "%s %s %s\n", items[i].name, items[i].company, items[i].ID);*/
//this is commented part was not working part... More about this in EDIT
fscanf(fp, "%s %s %s\n", items[i].name, items[i].company, items[i].ID);
printf("Name: %s", items[i].name); // For first item it prints:
// Name: #Name
}
}
return 0;
}
What is wrong here?
EDIT
I've replaced the code but now it reads first line as well. Is there a way to ignore header of file (first line)?
Try This,
#include <stdio.h>
#define TEXT_LEN 100
typedef struct
{
char name[TEXT_LEN];
char company[TEXT_LEN];
char ID[TEXT_LEN];
}Data_t;
int loadDataFromFile(Data_t *items, long len, char *inputFile) // change len as unsigned
{
FILE *fp;
char ch;
long i;
if ( ( fp = fopen(inputFile, "r") ) )
{
while( ( ch = getc(fp) != '\n') && ch!=EOF ); //To ignore first line
printf("Reading...\n");
for (i = 0; i < len && (fscanf(fp, "%s %s %s", items[i].name, items[i].company, items[i].ID) == 3); i++)
{
printf("\n#Name: %s #Company: %s #ID: %s", items[i].name, items[i].company, items[i].ID);
}
}
else
{
printf("File Error");
return 0;
}
return i;
}
int main()
{
Data_t data[2];
int n;
if(n=loadDataFromFile(data,2,"Txt")) //2 is number of line
{
printf("\n\nReaded !\n");
for(int i=0;i<n;i++)
printf("\n#Name: %s #Company: %s #ID: %s",data[i].name,data[i].company,data[i].ID);
}
return 0;
}
Txt:
#Name #Company #ID
Name1 Brand1 1234
Name2 Brand2 5678
Output:
Reading...
#Name: Name1 #Company: Brand1 #ID: 1234
#Name: Name2 #Company: Brand2 #ID: 5678
Readed !
#Name: Name1 #Company: Brand1 #ID: 1234
#Name: Name2 #Company: Brand2 #ID: 5678
[Done] exited with code=0 in 1.227 seconds
the following proposed code:
cleanly compiles
performs the desired functionality
properly discards the first line of the input file (the column headers)
properly checks for errors
properly checks that the data array is not overflowed
assures the fields in the data array are not overflowed when calling sscanf()
properly assures the input file can be read
and now, the proposed code:
#include <stdio.h>
#include <stdlib.h>
#define TEXT_LEN 21
struct MyStruct
{
char name[TEXT_LEN];
char company[TEXT_LEN];
char ID[TEXT_LEN];
};
typedef struct MyStruct Data_t;
long loadDataFromFile( Data_t *items, long len, char *inputFile )
{
FILE *fp = fopen(inputFile, "r");
if( ! fp )
{
perror( "fopen to read file failed" );
exit( EXIT_FAILURE );
}
// read/discard first line:
char buffer[1024];
if( ! fgets( buffer, sizeof( buffer ), fp ) ) // column header line
{
perror( "fgets failed to read column headers from input file" );
exit( EXIT_FAILURE );
}
long i = 0;
while( i < len && fgets( buffer, sizeof( buffer ), fp ) )
{
if( sscanf(buffer, "%20s %20s %20s", items[i].name, items[i].company, items[i].ID) != 3 )
{
break;
}
printf("Name: %s", items[i].name);
i++;
}
return i;
}
you coult try changin
fscanf(fp, "%s %s %s\n", items[i].name, items[i].company, items[i].ID);
to
fscanf(fp, "%s\t%s\t%s\n", items[i].name, items[i].company, items[i].ID);
and also iterating on the file lines could be done better by using something like this
while (!EOF) {/*Code*/}

how to find character that we want from another txt in c program?

I need to create a c program to find 'a' character in a sentence from another file. I have done the coding but still, do not get the correct result. What is wrong with my coding? the sentence in the okeya.txt is kazega hukeba okeyaga moukaru, but when I compile the program, the result is "found at 85"
#include <stdio.h>
#include <stdlib.h>
#define x_size 80
int main( void ){
char filename[] = "okeya.txt"; FILE *fp;
char input[ x_size ];
char find = 'a';
char *poin;
poin=filename;
char *p = input;
if( (fp = fopen( filename,"r" ) ) == NULL ){ printf( "?????????????" );
exit( -1 );
}
while( fgets( input , x_size , fp ) != NULL );
fclose(fp);
while(*poin!= '\0'){
if(*poin == find){
printf("\n found at %d .\n", poin-input + 1);
}
poin ++;
}
return 0;
}

How can I navigate through an array of strings of any length in C?

Understanding handling direct pointers in C
Here is a code that works for an array of strings for fixed number of items and fixed line length :
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXNAMELEN 100
#define MAXLINELEN 100
#define MAXITEMS 1000
int main(int argc, char ** argv) {
FILE * infile, * outfile;
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
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);
}
Problem description and code
If I try to read an input.txt file that is within MAXLINELEN and MAXITEMS, the program works fine. Now imagine I am reading from a much larger "inputfile" line by line where maximum line length could be anything, then I would have to use a character pointer (char*) to read the input. char* linesptr[MAXITEMS];
Here is my code where I am trying to accomplish reading from an input file line by line delimited by a newline character.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#define MAXNAMELEN 1000
#define MAXLINELEN 1000
#define MAXITEMS 100000
char* linesptr[MAXITEMS];
int
main(int argc, char ** argv) {
FILE * infile, * outfile;
char name[MAXNAMELEN];
char line[MAXLINELEN];
int i, items = 0;
printf("Enter a source filename: ");
fgets(name, MAXNAMELEN, stdin);
name[strlen(name)-1] = '\0'; // strip newline
printf("%s infile \n",name);
infile = fopen(name, "r");
while (fgets(line, MAXLINELEN, infile)) {
int length = strlen(line);
line[length-1] = '\0';
linesptr[items] = line; *<- I am writing to the same mem location*
printf("the input string %d is : %s \n",items, linesptr[items]);
items++;
}
qsort(linesptr, 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(linesptr[i], outfile);
}
fclose(infile);
fclose(outfile);
}
PROBLEM
I am copying the pointer address into the nth cell of the array linesptr where nth is the value=items (Here is the reference line from the code: linesptr[items] = line;). so when you print the final answer, I am referencing the same memory address to the buffer named line, the memory location at line will always point to the most recent fgets(). I understand the error but I do not know how to fix the issue. I would appreciate any help to fix the bug in the code.
Copy the line to a dynamically-allocated string.
while (fgets(line, MAXLINELEN, infile)) {
int length = strlen(line);
if (length > 0 && line[length-1] == '\n') {
line[length-1] = '\0';
length--;
}
char *linecopy = malloc(length+1);
strcpy(linecpy, line);
linesptr[items] = linecpy;
printf("the input string %d is : %s \n",items, linesptr[items]);
items++;
}
And if you want to handle more than MAXITEMS lines, you should allocate linesptr using malloc() as well. When you get to the current size of linesptr you can use realloc() to make it longer. See Read unknown number of lines from stdin, C for detailed code.
See How to qsort an array of pointers to char in C? for the proper way to sort an array of pointers to strings.
You ask for a example, so here it is:
the following proposed code:
is written for readability
checks for and handles error conditions
makes use of getline() and realloc()
is not as efficient as it could be because it calls realloc() for every line in the source file.
properly/safely uses strcspn() for removing any (possible) trailing newline characters
could have simplified the code by extracting the 'cleanup' to a sub function rather than repeating the same 'cleanup' code when ever an error was encountered.
used size_t rather than int for indexes into arrays to avoid implicit conversions
minimized the scope of variables where possible
passes proper third parameter to qsort()
properly implements the compare() helper function for qsort()
and now, the proposed code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXNAMELEN 1024
// prototypes
int compare(const void *, const void *);
int main( void )
{
printf("Enter a source filename: ");
char name[ MAXNAMELEN ];
if( !fgets(name, sizeof( name ), stdin) )
{
perror( "fgets for input file name failed" );
exit( EXIT_FAILURE );
}
// implied else, fgets for input file name successful
name[strcspn( name, "\n" ) ] = '\0'; // strip newline
printf("%s infile \n",name);
FILE *fp_in = fopen(name, "r");
if( !fp_in )
{
perror( "fopen for input file failed" );
exit( EXIT_FAILURE );
}
// implied else, fopen for input file successful
char **linesarray = NULL;
size_t numLines = 0;
char *line = NULL;
size_t lineLen = 0;
while( getline( &line, &lineLen, fp_in ) != -1 )
{
char ** temp = realloc( linesarray, (numLines+1) * sizeof( char* ) );
if( !temp )
{
perror( "realloc failed" );
fclose( fp_in );
for( size_t i = 0; i< numLines; i++ )
{
free( linesarray[i]);
}
free( linesarray );
exit( EXIT_FAILURE );
}
// implied else, realloc successful
linesarray = temp;
linesarray[ numLines ] = line;
numLines++;
// prep for next iteration
line = NULL;
lineLen = 0;
}
free( line );
fclose( fp_in );
//puts( "all file read in" );
qsort( linesarray, numLines, sizeof( char * ), compare );
//puts( "file sorted" );
printf("Enter a destination filename: ");
if( !fgets(name, sizeof(name), stdin) )
{
perror( "fgets for output file name failed" );
for( size_t i = 0; i< numLines; i++ )
{
free( linesarray[i]);
}
free( linesarray );
exit( EXIT_FAILURE );
}
// implied else, fgets() for output file name successful
name[strcspn( name, "\n" ) ] = '\0'; // strip newline
FILE *fp_out = fopen(name, "w");
if( !fp_out )
{
perror( "fopen for output file failed" );
for( size_t i = 0; i< numLines; i++ )
{
free( linesarray[i]);
}
free( linesarray );
exit( EXIT_FAILURE );
}
// implied else, fopen for output file successful
for (size_t i=0; i<numLines; i++)
{
if( fputs(linesarray[i], fp_out ) == EOF )
{
perror( "fputs failed" );
fclose( fp_out );
for( size_t i = 0; i< numLines; i++ )
{
free( linesarray[i]);
}
free( linesarray );
exit( EXIT_FAILURE );
}
}
fclose( fp_out );
for( size_t i = 0; i< numLines; i++ )
{
free( linesarray[i]);
}
free( linesarray );
}
int compare(const void *ls, const void *rs )
{
char *leftSide = *(char**)ls;
char *rightSide = *(char**)rs;
return strcmp( leftSide, rightSide );
}
Here is the complete working solution to read in a file (big data), sort it and write it to a file:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#define MAXNAMELEN 1000
#define MAXLINELEN 5000
#define MAXITEMS 100000
char* linesptr[MAXITEMS];
int compare_function(const void *name1, const void *name2)
{
const char *name1_ = *(const char **)name1;
const char *name2_ = *(const char **)name2;
return strcmp(name1_, name2_);
}
int
main(int argc, char ** argv)
{
FILE * infile, * outfile;
char name[MAXNAMELEN];
char line[MAXLINELEN];
int i, items = 0;
printf("Enter a source filename: ");
fgets(name, MAXNAMELEN, stdin);
name[strlen(name)-1] = '\0'; // strip newline
infile = fopen(name, "r");
while (fgets(line, MAXLINELEN, infile)) {
int length = strlen(line);
line[length-1] = '\0';
char *linecopy = malloc(length);
strcpy(linecopy, line);
linesptr[items] = linecopy;
items++;
}
qsort(linesptr, items, sizeof(char *), compare_function);
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++) {
fprintf(outfile, "%s\n", linesptr[i]);
}
fclose(infile);
fclose(outfile);
}

reading words/strings from file+length of them - c

i have a problem with my c program,
it should read words/strings from txt file, then count length of them.
when i run my program, it doesnt response
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *f;
char c;
char word[50];
int a,b=0;
if ((f = fopen("file.txt", "r")) == NULL)
{
printf("CANT OPEN THE FILE" "\n");
return 1;
}
while((c=fgetc(f))!=EOF){
if (c==' ')b++;
word[b]=word[b]+c;
}
for (a=0;a<b;a++){
printf("%c ",word[0]);
}
return 0;
}
it should do this: first i open my file, then i will read every char from this file+storing this chars in array word, then when blank space occurs(' '), it should write chars to next index of array, so the words will be created on different indexes of array
then it should count the lenght of words, but that should be easy to implement, thx a sorry for my english
They are ALOT of errors with the code you shared :
J is not declared, so you need to add int j = 0; I'm assuming than j is the number on whitespace on your doc.
word[b]=word[b]+c; get changed into word[b]= c;
You add an incremntation on b in your loop then, so you wont write only on word[0].
Your printing is bad aswell, you would only show the first letter over and over.
This is the final code, corrected. It shows the entire file if the file is less than 200 caracters. J is the number of whitespace.
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *f;
char c;
char word[200];
int a,b=0;
int j = 0;
if ((f = fopen("file.txt", "r")) == NULL)
{
printf("CANT OPEN THE FILE" "\n");
return 1;
}
while((c=fgetc(f))!=EOF){
if (c==' ')j++;
word[b]= c;
b++;
}
for (a=0;a<b;a++){
printf("%c",word[a]);
printf("The file contains %d caracters, and %d whitespaces", b, j);
}
return 0;
}
By the way, next time. try to compile at least. It's clear that you put no effort into it before submitting a question here on SO.
the following compiles and meets your description of what needs to be done
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // memset
#define MAX_WORD_LENGTH (50)
struct wordStruct_t
{
char word[MAX_WORD_LENGTH];
};
int main()
{
FILE *fp;
int c;
char word[50]; // assume max word length is < 50
int i = 0; // word byte index
int wordCount = 0; // count of words read
struct wordStruct_t * wordArray = NULL;
char * testArray = NULL;
if ((fp = fopen("file.txt", "r")) == NULL)
{
perror( "fopen failed for read of file.txt");
exit( EXIT_FAILURE );
}
// implied else open successful
memset( word, 0x00, sizeof( word ) );
while((c=fgetc(fp))!=EOF)
{
if( (c!=' ') && (c != '\n') )
{ // then letter to add to current word (should also check for word overflow)
word[i++] = c;
}
else
{ // else, end of word found
// allocate max room for new word
if( NULL == (testArray = realloc( wordArray, sizeof(struct wordStruct_t) * (wordCount+1)) ) )
{
perror( "realloc failed");
free( wordArray );
fclose( fp );
exit( EXIT_FAILURE );
}
// implied else, realloc successful
wordArray = (struct wordStruct_t*)testArray;
strcpy( wordArray[wordCount].word, word );
memset( word, 0x00, sizeof(word) ); // prep for next word
} // end if
} // end while
for (i = 0; i< wordCount; i++)
{
printf("word: %d is %s and contains %d bytes\n",
i,
wordArray[i].word,
(int)strlen(wordArray[i].word ) );
}
free( wordArray );
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h> //for string functions
int main()
{
FILE *f;
int c; //c should be an int
char word[50];
char *ptr; //to store each word
int a,b=0;
if ((f = fopen("file.txt", "r")) == NULL)
{
printf("CANT OPEN THE FILE" "\n");
return 1;
}
while((c=fgetc(f))!=EOF){
word[b++]=c;
}
for (a=0;a<b;a++){
printf("%c ",word[a]); //word[a] not word[0]
}
ptr=strtok(word," ");//get first word
a=0;
while(ptr!=NULL)
{
printf("Word %d which is %s is %d letters long",++a,ptr,strlen(ptr));
ptr=strtok(NULL," "); //get next word
}
return 0;
}

Resources