Unable to read a file and pass into arguments - c

1) I'm trying to open a file, read the mix data (ints, chars and strings) and store them into args.
1.1) so in the sample.txt is a total of 13 (excluding args[0])
2) Need to read a file from terminal "./myprog.c < sample.txt"
Heres my code and have no idea where i went wrong:
sample.txt:
123 213 110 90 1
hello my friend
boo bleh
a b c
myprog.c:
#include <stdio.h>
int main()
{
int i = 1;
FILE *fstin=fopen(argv[0], "r"); //open the file
if (fstin == NULL) {
puts("Couldn't fopen...");
return -1;
}
//Getting all the inputs from file
while ((fscanf(fstin, "%d", argv[i])) != EOF){
i++;
}
fclose(fstin);
for (i=0; i<10; i++) {
printf("%d\n",argv[i]);
}
return 0;
}
Any help is greatly appreciated!
PS: Would like if anyone could post their complete solution? Will upload unto this post and let everyone have a review of this problem
PPS: Please excuse the poor level of coding as I am a beginner and completely new to C.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int ac, char *av[]){
int i, argc=0;
char **argv=NULL, data[16];
FILE *fstin = stdin;
if(ac == 2){
if(NULL==(fstin = fopen(av[1], "r"))){
puts("Couldn't fopen...");
return -1;
}
}
while (1==fscanf(fstin, "%15s", data)){
argv = realloc(argv, (argc+1)*sizeof(char*));
argv[argc] = malloc(strlen(data)+1);
strcpy(argv[argc++], data);
}
if(ac == 2)
fclose(fstin);
for (i=0; i<argc; ++i) {
printf("%s\n", argv[i]);
}
//deallocate
return 0;
}

You are making mistake at 2nd point where you divert your file to other file which is wrong. Actually you need to first compile and need to make executable.
gcc -o my_prog ./myprog.c -Wall
You need to execute this program as below to read file from c program:
./my_prog ./sample.txt
As you are new to C programming first go to man pages related to file operations.
Solution:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
//If command line argument is not inserted then stop operation
if (2 != argc) {
printf("Invalid number of arguments : %d\n", argc);
return -1;
}
int size = 0, ret = 0;
char *data = NULL;
FILE *fp = NULL;
//Open file in read mode given from command line argument
if (NULL != (fp = fopen(argv[1], "r")))
{
//Find size of file
fseek(fp, 0L, SEEK_END);
size = ftell(fp);
fseek(fp, 0L, SEEK_SET);
//if file is empty no need to read it.
if (size > 0)
{
//Data pointer which contains file information
data = (char *) calloc(sizeof(char), size);
if (NULL != data)
{
//Read whole file in one statement
fread(data, sizeof(char), size, fp);
printf("File %s is readed successfully\n", argv[1]);
printf("Data:\n");
printf("%s\n", data);
free(data); data = NULL;
}
else
{
perror("memory allocation failed\n");
ret = -1;
}
}
else
{
printf("File %s is empty\n", argv[1]);
}
fclose(fp); fp = NULL;
}
else
{
perror("File open failed\n");
ret = -1;
}
return ret;
}
Now Test it on your setup and if any query please post comments.

Related

Can't read file in C using fread()

Program asks for input and stores it in a variable, then confirms the operation printing the content of the file. Or at least it had to, when the program ends it doesn't print the file content, I can't seem to find an answer, I've been looking in the docs but can't really figure it out.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE * file1 = fopen(".out", "w+");
char *s = malloc(513);
fgets(s, 513, stdin);
if (fprintf(file1, "%s", s) < 0)
{
printf("Something failed while writing to the file\n");
return 1;
}
else
{
char *t = malloc(513);
fread(t, sizeof(char), 1, file1);
printf("Success! Input was: %s \n", t);
return 0;
}
}
P.S: Very new to C, though it may seem obvious for you I have no clue whatsoever.
There are 2 issues here,
1 - you wrote to the file handler and you are trying to read from that point onwards - you didnt rewind the file pointer!
2 - you are just reading 1 character and not the amount you wrote to it!
#include <string.h>
...
int n = strlen(s);
rewind(file1); // rewind before read
fread(t, sizeof(char), n, file1); // read as much as you wrote
Some problems in your code:
You are not checking the return value of fopen(), malloc(), fgets() and fread().
You are writing one character to the output stream, without rewinding it.
Here's how your code should look like:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
FILE * file1 = fopen(".out", "w+");
if (!file1) {
printf("Could not open file.\n");
return 1;
}
const size_t n = 513; // Use constants, not litterals.
char *s = malloc(sizeof(char) * n);
if (!s) {
printf("Internal error.\n");
fclose(file1);
return 1;
}
if (!fgets(s, n, stdin)) {
printf("Input failed.\n");
fclose(file1);
return 1;
}
if (fprintf(file1, "%s", s) < 0) {
printf("Something failed while writing to the file\n");
fclose(file1);
return 1;
}
char *t = malloc(sizeof(char) * n);
if (!t) {
printf("Internal error.\n");
fclose(file1);
return 1;
}
rewind(file1);
int ret = fread(t, sizeof(char), n, file1); // Read n characters, not 1.
if (ret != strlen(s)) {
if (feof(file1)) {
printf("Error reading .out: unexpected end of file.\n");
} else if (ferror(file1)) {
perror("Error reading .out");
}
fclose(file1);
return 1;
}
printf("Success! Input was: %s \n", t);
}

Why is this function not copying the input file?

I'm just getting started into file I/O and am trying to build a function that will simply copy a file to destination.
This program compiles however an empty file is created and nothing is copied. Any advice?
#include <stdio.h>
int copy_file(char FileSource[], char FileDestination[]) {
char content;
FILE *inputf = fopen(FileSource, "r");
FILE *outputf = fopen(FileDestination, "w");
if (inputf == NULL)
;
printf("Error: File could not be read \n");
return;
while ((content = getc(inputf)) != EOF) putc(content, inputf);
fclose(outputf);
fclose(inputf);
printf("Your file was successfully copied");
return 0;
}
int main() {
char inputname[100];
char outputname[100];
printf("Please enter input file name: \n");
scanf("%s", &inputname);
printf("Please write output file name: \n");
scanf("%s", &outputname);
copy_file(inputname, outputname);
return 0;
}
There are few bugs in the code you mentioned. These two below statement
scanf("%s", &inputname);
scanf("%s", &outputname);
Are wrong as inputname and outputname are char array and array name itself address so you no need to give &inputname to scanf(). For e.g
scanf("%s",inputname);
scanf("%s",outputname);
Also ; at the end of if statement is not serving correct purpose as you expected.
This
if(inputf == NULL);
Should be
if(inputf == NULL){
/*error handling */
}
As pointed by other, getc() returns int not char. From the manual page of getc()
int getc(FILE *stream);
And this
putc(content, inputf);
Change to
putc(content, outputf); /* write the data into outputf */
Your line :
putc(content, inputf);
needs to change to
putc(content, outputf);
This code has a lot of problems:
if(inputf == NULL);
printf("Error: File could not be read \n");
return;
It is the equivalent of
if(inputf == NULL)
{
;
}
printf("Error: File could not be read \n");
return;
You have a stray ; that terminates you if statement, and whitespace doesn't matter much at all with C.
So your if statement does nothing, and your code will always emit the "Error: File could not be read" message and return without doing anything else.
What you probably want:
if(inputf == NULL)
{
printf("Error: File could not be read \n");
return;
}
This is a perfect example of why a lot of C programmers always use braces after if statements. ALWAYS.
There are multiple problems in your code:
content must be declared as int: getc() returns an int with the value of the byte read from the file or the special negative value EOF at end of file. Storing that to a char variable loses information, making the test for EOF either ambiguous (if char is signed) or always false (if char is unsigned by default).
you should pass outputf to putc.
you should return from the copy_file function if fopen fails to open either file.
you should pass the maximum number of characters to read for the filenames
you should check the return value of scanf() to avoid undefined behavior on invalid input.
Here is a corrected version:
#include <stdio.h>
int copy_file(const char *FileSource, const char *FileDestination) {
int content;
FILE *inputf, *outputf;
if ((inputf = fopen(FileSource, "r")) == NULL) {
printf("Error: cannot open input file %s\n", FileSource);
return -1;
}
if ((outputf = fopen(FileDestination, "w")) == NULL) {
printf("Error: cannot open output file %s\n", FileDestination);
fclose(inputf);
return -1;
}
while ((content = getc(inputf)) != EOF)
putc(content, inputf);
fclose(outputf);
fclose(inputf);
printf("Your file was successfully copied");
return 0;
}
int main() {
char inputname[100];
char outputname[100];
printf("Please enter input file name: \n");
if (scanf("%99s", inputname) != 1)
return 1;
printf("Please write output file name: \n");
if (scanf("%99s", &outputname) != 1)
return 1;
copy_file(inputname, outputname);
return 0;
}
Use sendfile() is more simple and efficient for copying file. You can view more detail about sendfile() by man sendfile.
#include <stdio.h>
#include <string.h>
#include <sys/sendfile.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
if (argc < 3)
{
printf("Usage: %s <srcfile> <dst_file>\n", argv[0]);
return 1;
}
char *src_file = argv[1];
char *dst_file = argv[2];
int src;
int dst;
ssize_t size;
struct stat stat_buf;
if ((src = open(src_file, O_RDONLY)) < 0)
{
printf("Can not open %s\n", src_file);
return -1;
}
if (fstat(src, &stat_buf) < 0)
{
printf("Can stat %s\n", src_file);
close(src);
return -2;
}
if ((dst = open(dst_file, O_CREAT|O_WRONLY, stat_buf.st_mode)) < 0)
{
printf("Can not open %s\n", dst_file);
return -1;
}
if ((size = sendfile(dst, src, NULL, stat_buf.st_size)) < 0)
{
printf("Fail to copy file, size: %ld\n", size);
}
else
{
printf("Success, size: %ld\n", size);
}
close(src);
close(dst);
return 0;
}

C. Can't open a text file with fopen on Windows Vista

I wanted to learn how to use getc function in C so I wrote a little program that is supposed to give the first letter of a text file as an output.
Here's how it looks:
int main()
{
int character;
FILE *file;
file = fopen("file.txt", "r");
if(file == NULL)
printf("can't open\n");
character = getc(file);
printf("%c", character);
fclose(file);
return 0;
}
It fails to open the file.txt file and I can't figure out why. file.txt is in the same folder as my program's .exe file. I'm using Windows Vista.
Thanks in advance
This extracts the program's location from argv[0]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MYFILE "plik.txt"
int main(int argc, char *argv[]) {
char fname[_MAX_PATH+1];
int znak;
FILE *plik;
char *ptr;
strcpy(fname, argv[0]);
ptr = strrchr(fname, '\\');
if(ptr == NULL) {
strcpy(fname, MYFILE);
}
else {
strcpy(ptr+1, MYFILE);
}
plik = fopen(fname, "r");
if(plik == NULL) {
printf("Can't open %s\n", fname);
}
else {
znak = getc(plik);
printf("First char of %s is %c\n", fname, znak);
fclose(plik);
}
getchar();
return 0;
}
Try
if (plik == NULL) { perror("plik.txt"); exit(EXIT_FAILURE); }
for a better understanding of the cause of error.

C - Writing on second line of file

Im doing the Hangman game on C and I have a trouble on one of the txt files.
I'm trying to append "num_letters" on the second line of the file.My code prints on new line everytime I guess. Is there a "lightweight" way to skip the first line and append on the second one?
void write_stats(int tries, int num_letters)
{
FILE *stats;
stats = fopen("C:\\Users\\rjmal\\Documents\\CLION PROJECTS\\JogoDaForca\\stats.txt", "a");
fprintf(stats," %d",tries);
fprintf(stats,"\n %d",num_letters);
fclose(stats);
}
Here you go:
/* Compiles with: gcc main.c -o test -pedantic -Wall -Wextra */
#include <stdio.h>
int write_stats(const int tries, const int num_letters, FILE* file) {
if (!file)
return -1;
const int written = fprintf(file, "%d\n%d", tries, num_letters);
if (written < 0)
return -1;
return 0;
}
int read_stats(int* tries, int* num_letters, FILE* file) {
if (!file)
return -1;
if (fscanf(file, "%d\n%d", tries, num_letters) != 2)
return -1;
return 0;
}
int main() {
/* writing stats */
FILE* w_stats = fopen("stats.dat", "w");
if (!w_stats) {
fprintf(stderr, "Could not open the file specified!\n");
return 1;
}
if (write_stats(3, 8, w_stats) != 0) {
fprintf(stderr, "Problem occoured while writing stats!\n");
fclose(w_stats);
return 1;
}
fclose(w_stats);
/* reading the stats */
FILE* r_stats = fopen("stats.dat", "r");
if (!r_stats) {
fprintf(stderr, "Could not open the file specified!\n");
return 1;
}
int tries, num_letters;
if (read_stats(&tries, &num_letters, r_stats) != 0) {
fprintf(stderr, "Problem occoured while reading stats!\n");
fclose(r_stats);
return 1;
}
fclose(r_stats);
printf("tries: %d, num_letters: %d\n", tries, num_letters);
return 0;
}
Hopefully it makes sense, I think this does not need any further explanation, since the code explains it itself. However, if you want to clarify something, feel free to ask.

Why wont the program read from the 2 argument file?

So the assignment is to implement a substring search program using an input file to be searched from and an input to be searched. I created the following code:
#include <stdio.h>
#include <string.h>
int main(int argc,char *argv[])
{
FILE *fp;
fp = fopen(argv[1],"r");
if (fp == NULL)
{
printf("Error");
return 0;
}
char* tmpp[100];
int count = 0;
char* nexts = argv[2];
char* tmp = fgets(tmpp,100,fp);
while(tmp = strstr(tmp,nexts))
{
count++;
tmp++;
}
printf("%d\n\n",count);
fclose(fp);
return 0;
}
The program compiles but when i go to implement it in the ubuntu terminal as:
echo "aabb" >beta
./a.out beta a
1
Why isnt the program using the first argument (argv[1]) as beta and the second argument (argv[2]) as a correctly?
You should open a file and then read bytes from that file into temporary buffer:
FILE *file = fopen("file", "r");
while (1) {
char buffer[BUFSIZ+1];
size_t nread = fread(buffer, 1, sizeof(buffer)-1, file);
if (nread == 0) break; // read error or EOF
buffer[nread] = 0;
// chunk with BUFSIZ amount of bytes is available via buffer (and is zero-terminated)
}
If you want to search for string/pattern in a file, be aware that looked pattern in file may cross your chunk-size boundary, for example: you look for "hello", and BUFSIZ is 512. File contains "hello" at byte 510. Obviously, if you read by 512, you will get the first chunk ending with "he", and the second chunk starting with "llo". Probability of this situation is nonzero for all chunk sizes (except SIZE_MAX, but that buffer size is impossible by other reasons). Dealing with borders may be very complicated.
Close...but this is closer:
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
if (argc != 3)
{
fprintf(stderr, "Usage: %s file pattern\n", argv[0]);
return 1;
}
FILE *fp = fopen(argv[1], "r");
if (fp == NULL)
{
fprintf(stderr, "Error: failed to open file %s for reading\n", argv[1]);
return 1;
}
char tmpp[1000];
int count = 0;
char* nexts = argv[2];
while (fgets(tmpp, sizeof(tmpp), fp) != 0)
{
char *tmp = tmpp;
while ((tmp = strstr(tmp, nexts)) != 0)
{
count++;
tmp++;
}
}
printf("%d\n", count);
fclose(fp);
return 0;
}
The main difference is that this loops reading multiple lines from the input file. Yours would only work on files with a single line of input.

Resources