Passing a file as an argument and reading the data - c

So I am trying to write a C code that takes in a file name as the argument and reads the file and stores it into an array. I have tried but failed epically :(
Can anyone please point me in the right direction? Here is what I came up with (I know it may be completely off track :/ )
#include <stdio.h>
int main (int argc, char *argv[]) {
char content[500];
int k=0;
FILE* inputF;
inputF = fopen("argv[0]", "r");
do {
fscanf(inputF, "%c", &content[k]);
k++;
} while (content[k] != EOF );
return 0;
}

You passed "argv[0]" string to fopen, I'm sure that isn't the name of you file you are trying to open.
You should pass a pointer to a string that contains the file name.
inputF = fopen(argv[1], "r");
Also note the usage of argv[1] not argv[0].
argv[0] contains the full filepath and name of the executable and argv[1] the first string entered as command line parameter.

A couple of points to help get you started:
argc is the number of arguments, and the first argv pointer is the name of the executable file. The second is what you want.
You have to check that your file pointer is valid before trying to use it.
Maybe look at using fgetc to read each character, and test for EOF.
You need to check that you don't overrun your content buffer.
If you're stuck, here's an example of a main loop using a do while:
do {
ch = fgetc(fp);
content[a] = ch;
a++;
} while (ch != EOF && a < 500);
This will store an EOF (if found) in your array.

Related

Issue opening a double pointer char element for reading it as text file

i'm new in C programming and I am trying to open a txt file for reading it.
I have a text file with different file names I want to read, each one in a different line. I created a function txt_to_stations() that reads this file and returns a double pointer to char, I guess it has to be a double pointer because I want to save a string of char strings. This is the function.
char** txt_to_stations(const char* txt_file){
FILE* file;
file = fopen(txt_file,"r");
int line_count = 0;
int char_count = 0;
int len = 1;
char tmp_station[25];
char** stations = (char**)malloc(len*sizeof(char*));
char character;
while(!feof(file)){
character = fgetc(file);
if(character!='\n'){
tmp_estation[char_count] = character;
char_count++;
}else if(character=='\n'){
stations = (char**)realloc(stations,len*sizeof(char*));
stations[line_count] = (char*)malloc(char_count*sizeof(char));
strcpy(stations[line_count],tmp_station);
len++;
line_count++;
char_count = 0;
}
}
fclose(file);
return stations;
}
My text file is this one. "stations.txt"
weatherdata-429-81.csv
weatherdata-429-84.csv
weatherdata-429-88.csv
The problem comes when I try from the main function to read this files. The function works great because if I
char** stations = txt_to_stations("stations.txt") and then for example
printf("station1: %s\n",stations[0]) it prints in terminal weatherdata-429-81.csv.
But if I define a new file in main function
FILE* reading;
reading = fopen(stations[0]);
if(reading==NULL){
printf("csv file cant be opened");
}
It prints "csv file cant be opened", which means fopen(stations[0])==NULL but i does not cause if I simply change stations[0] by fopen("weatherdata-429-81.csv") it works. It may be a rookie error but I understand that stations[0] == weatherdata-429-81.csv (as char*)
I really tried converting stations[0](char*) to a const char* , and also in "stations.txt" writing each name into double quotes,but anyways it did not work at all. Someone helping please.
I ran your code through a debugger, and found some mistakes. I commented them(and some other points) out for you.
char** txt_to_stations(const char* txt_file)
{
FILE* file;
file = fopen(txt_file, "r");
if(file == NULL) // you forgot to error-check file. fopen is one of the most likely functions to return NULL, so you really can't forget that
{
printf("Error opening file.");
exit(0); // exits your program, regardless of where you are, defined in stdlib.h
}
int line_count = 0;
int char_count = 0;
int len = 2; // I made len slightly bigger, nothing with a little bit of buffer and also allows you to keep space for the NULL terminator
char tmp_station[25] = {0}; // always a good idea to zero out an array you're creating, while testing I found some stray garbage characters at the end of one of the strings...
char** stations = (char**) malloc(len * sizeof(char*));
char character;
while (1) // this should run forever and you should break out of this loop when you reach the end of the file
{
// this is one way to properly find the end of a file, don't put feof call inside the while condition
if (feof(file))
break;
// fgets() would save you a lot of time, but oh well, don't wanna change your code too much...
character = fgetc(file);
if(character != '\n')
{
tmp_station[char_count] = character;
char_count++;
}
else // removed the if here cause it was redundant.... else means that it must be a newline character
{
tmp_station[char_count] = '\0'; // you forgot to null-terminate the string you took into tmp_station. this is the main reason the function wasn't working
stations = (char**) realloc(stations, len*sizeof(char*));
stations[line_count] = (char*) malloc(char_count*sizeof(char));
strcpy(stations[line_count], tmp_station);
len++;
line_count++;
char_count = 0;
// it's a good idea to terminate an array of pointers with NULL, how will you know you reached the end of the array?
stations[line_count] = NULL;
}
}
fclose(file);
return stations;
}
There's a tiny little problem with your code as of now. See, because you only import a line into the array of pointers if and only if a newline is found, that means if the last line of your stations.txt file does not have a newline, that line will not get imported into the array. There are two solutions.
Add an extra newline at the end of your text file like this
weatherdata-429-81.csv
weatherdata-429-84.csv
weatherdata-429-88.csv
Change the code so you can import the last line regardless of whether it has a newline character or not.
Use fgets(). It will keep reading the entire file until it reaches the end of the file, so you can store whatever it returns inside an array and manually remove the newline characters that it generates yourself.

File I/O word count program in C

I know there are several asks already regarding this topic, but it seemed like those were either not completely answered or hard to apply to my code, so I apologize if this is a repeat.
I am having trouble with the below function in an overall I/O program that also does word and line count (those work). char* filename is pulled from the command line. In this example it is pulling from a txt file with lorum ipsum. (69 words) In theory the below function should read from filename and write it to an array. Then read that array and checks if the current character is a space ' ' and the next character is not. It currently returns 0 regardless.
int wordcount(char* filename) {
int wc=0,i=0,z=0;
char w, test[1000];
FILE *fp;
fp = fopen(filename, "r");
while (feof(fp) == 0) {
fscanf(fp, "%c", &test[i]);
i++;
}
while (z>i-1) {
if (test[z] = ' ' && test[z+1] != ' ' ) {
wc++;z++;
}
}
return wc;
}
NOTES: i know it's super inefficient to declare a 1000 char array, but I wasn't sure how else to do it. If you have any improvements or other methods to accomplish this, it would be greatly appreciated if you shared. Also, i'm aware that this currently ignores others types of whitespace, but I am just testing this first and will expand after.
Thanks for any assistance.
There is a sample function doing what you need. Some suggestions for you code, fopen() must be followed by fclose() when you no longer need the file. Always check if the pointer returned by fopen is not NULL and do nothing in that case, just return error code. The presence of new word can be safely detected by the space character followed by a non space character in that case increment world count ++wc. Use getc() to read one character from the file object and use isspace() function to check if the character is a space one. You don't need an array to store the file if no one modifies that file during the worldcount run.
int wordcount(const char* filename)
{
int wc=0;
char c;
FILE *fp;
fp = fopen(filename, "r");
if(fp == NULL)
{
return -1;
}
bool previsspace = 1;
while ((c=getc(fp)) != EOF)
{
if (isspace(c)==0 && (previsspace==1)) ++wc;
previsspace = isspace(c);
}
fclose(fp);
return wc;
};
You will need the following include files:
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
The concrete problem why you always get a result of 0 words:
while (z>i-1) {
z is never larger than i-1. Probably you meant to loop while z is smaller than i-1 instead:
while (z<i-1) {
Additionally you only increment z when you find a word. You should increment it for every character you test, no matter if it's a space or not.

C program to read a text file line by line then print out those lines to the terminal

I want to have a c program read a text file line by line then print out those lines to the terminal.
My code
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char* line;
FILE *ifp;
ifp = fopen("BBE.txt", "r");
if (ifp == NULL)
{
printf("Error opening file!\n");
exit(1);
}
while (fscanf(ifp, "%s", line) == 1)
{
printf("%s\n", line);
}
fclose(ifp);
return 0;
}
The program when i try to run it does not print out anything to the terminal. This tells me that the while loop is not working but i am not to sure as to why.
Your loop is not working, because fscanf does not return just 1 on success.
According to the man page of fscanf, the return value has the following meaning:
RETURN VALUE
On success, these functions return the number of input items
successfully matched and assigned; this can be fewer than provided for, or even zero, in the event of an early matching failure.
The value EOF is returned if the end of input is reached before either the first successful conversion or a matching failure occurs. EOF is also returned if a read error occurs, in which case the error indicator for the stream (see ferror(3)) is set, and errno is set to indicate the error.
Additionally as already stated in another answer: You write to memory that is NOT YOUR memory:
char* line;
is just a the declaration of a pointer to a char. What you need is a contiguous array of char to write to.
You either can allocate this on the stack by declaring it:
char line[1000]; // Allocate a char array of the size of 1000.
or on the heap;
char* line = malloc(1000*sizeof(char)); // Allocate 1000 chars on the heap
here you have to free the memory afterwards
free(line);
You used *line without initialising it -> undefined behavior.
To fix that, you can use a char array instead:
char line[1000] = "";

How to save every line in file (IN C) in a variable? :)

I need to save every line of text file in c in a variable.
Here's my code
int main()
{
char firstname[100];
char lastname[100];
char string_0[256];
char string[256] = "Vanilla Twilight";
char string2[256];
FILE *file;
file = fopen("record.txt","r");
while(fgets(string_0,256,file) != NULL)
{
fgets(string2, 256, file);
printf("%s\n", string2);
if(strcmp(string, string2)==0)
printf("A match has been found");
}
fclose(file);
return 0;
}
Some lines are stored in the variable and printed on the cmd but some are skipped.
What should I do? When I tried sscanf(), all lines were complete but only the first word of each line is printed. I also tried ffscanf() but isn't working too. In fgets(), words per line are complete, but as I've said, some lines are skipped (even the first line).
I'm just a beginner in programming, so I really need help. :(
You're skipping over the check every odd number of lines, as you have two successive fgets() calls and only one strcmp(). Reduce your code to
while(fgets(string_0,256,file) != NULL)
{
if( ! strcmp(string_0, string2) )
printf("A match has been found\n");
}
FWIW, fgets() reads and stores the trailing newline, which can cause problem is string comparison, you need to take care of that, too.
As a note, you should always check the return value of fopen() for success before using the returned pointer.

Need help reading from a file in C

I have been looking around for a solution but cannot seem to find a solution to my question so I will ask it. I am working in C and am reading in a .txt and taking all the values and storing them in an array then doing various tasks with them. Now my problem is that no matter what I do I cannot get file pointer I create to point to the file for some reason. I have done this for projects in the past and have compared my code then to the current one and cannot see the issue. The filename needs to be read in from the command line as well. I think there is something wrong with what I'm passing through the command line but am not sure. I have stepped through and the filename is being passed correctly but when it tries to open I get a null pointer so there is just something I'm missing.
The text file will contain a series of numbers, the first number will be the number of numbers in the file after that first number. (So if the number is 10 then there will be ten numbers after 10 is read in) after that first number the remaining numbers will be 0-9 in a random order.
Below is my current chunk of code only involving reading of the file and storing its data. (I already know the array will be of size 10 which is why the array is declared with that size.)
int main(int argc, char *argv[])
{
char* filename = "numbers.txt";
int arr[10];
int numElem;
int indexDesired = 0;
FILE *fp;
fp = fopen(filename, "r"); // open file begin reading
if (!fp)
{
printf("The required file parameter name is missing\n");
system("pause");
exit(EXIT_FAILURE);
}
else
{
fscanf(fp, "%d", &numElem); //scans for the first value which will tell the number of values to be stored in the array
int i = 0;
int num;
while (i <= numElem) //scans through and gets the all the values and stores them in the array.
{
fscanf(fp, "%d", &num);
arr[i] = num;
i++;
}
fclose(fp);
}
}
***note: My sort and swap method work perfectly so I have omitted them from the code as the error happens before they are even called.
you said,
The filename needs to be read in from the command line as well.
However, you are using:
char* filename = "numbers.txt";
and
fp = fopen(filename, "r"); // open file begin reading
No matter what you are passing in the command line, the file you are trying to open is "numbers.txt".
Things to try:
Use the full path name of "numbers.txt" instead of just the name of the file.
char* filename = "C:\\My\\Full\\Path\\numbers.txt";
If that doesn't work, you will probably have to deal with permissions issues.
Pass the file name from the command line, using the full path. That should work if there are no permissions issues.
if ( argc < 2 )
{
// Deal with unspecified file name.
}
char* filename = argv[1];
Pass the relative path of the file name. If you are testing your program from Visual Studio, you have to make sure that you use the path relative to the directory from where Visual Studio launches your program.
while (i <= numElem)
should be
while (i < numElem)
Because in fscanf(fp, "%d", &numElem); you are scanning the number of elements.
Notice that the array in C starts from 0, so if say numElem is 10 arr[10] does not exist which can be harmful because arr goes from arr[0] to arr[9]
Also, you should check if numElem is lower than 10 before the while(i < numElem) loop.

Resources