The following code is supposed to read a text file character by character and count the frequency of their occurrence. However, on the Linux command line, it compiles and when I try to run it by the command ./program<file.txt it shows
useage: huffman <filename>
I don't know what's the error.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
int count[26];
int main(int argc, char ** argv)
{
unsigned char c;
FILE * file;
int i;
if ( argc != 2 ) {
fprintf(stderr, "Useage: huffman <filename>\n");
exit(1); // exit with error code
}
file = fopen(argv[1], "r");
assert( file != NULL );
c = fgetc(file);
while( !feof(file) ) {
c = fgetc(file);
count[c-'a']++;
}
for(i=0; i<26; i++)
printf("count[%c]=%d\n",65+i,count[i]);
fclose(file);
return 0;
As you execute it as
$ ./program < file.txt
you are calling the program with zero arguments and set its standard input stream to read from file.txt. Therefore, argc in your main is 1 and you get the error message you have placed for this case.
To solve this, you can either
run the program as it's supposed to (without shell redirection)
$ ./program file.txt
or modify your program such that it reads from standard input if called with no arguments. It may then be called either way.
Many POSIX commands use the convention that if called with no file names, they read from standard input instead. For example,
$ cat file.txt
outputs the contents of file.txt while
$ cat
parrots back at you everything you type.
To implement this, you'd need something like this.
FILE * file = NULL;
if (argc == 1)
{
file = stdin;
}
else if (argc == 2)
{
file = fopen(argv[1], "r");
if (file == NULL)
{
fprintf(stderr, "error: %s: %s: %s\n",
"cannot read file", argv[1], strerror(errno));
return EXIT_FAILURE;
}
}
else
{
fprintf(stderr, "error: %s\n", "too many arguments");
return EXIT_FAILURE;
}
assert(file != NULL); /* we have made this sure */
c must be an int.
Make sure c is in proper range before indexing the array.
c = fgetc(file);
if (islower((unsigned char)c)) count[c-'a']++; // assumes 'a' thru 'z' are sequential
You need to #include <ctype.h> for the correct prototype for islower()
Related
For example I have a text file includes "I'm having great day!", I want to count each character and word in this file.
in the example "there are 3 a, 1 m" etc.
I'm new at C and know how to open a file, how can find a specific char or word in file but couldn't figure this out. Can you help me pls.
The first thing you need to learn is how to open and process a file one character at a time. You can do this with a program like:
#include <stdio.h>
int main(int argc, char *argv[]) {
// Must provide one argument, the file to process.
if (argc != 2) {
fprintf(stderr, "Usage: myprog <inputFileName>\n");
return 1;
}
// Try to open the file.
FILE *inFile = fopen(argv[1], "r");
if (inFile == NULL) {
fprintf(stderr, "Cannot open '%s'\n", argv[1]);
return 1;
}
// Process file, character by character, until finished.
int ch;
while ((ch = fgetc(inFile)) != EOF) {
putchar(ch); // <accumulate>
}
// Close file and exit.
fclose(inFile);
// <output>
return 0;
}
Then it's a matter of changing the putchar call into whatever you need to do (accumulating character counts) and outputting that information before you exit from the main function.
I'm trying to write a simple main function that takes in a file through the command line, and prints all the words in the file.
However, I've followed several tutorials that just don't seem to work. Here's my code:
int main(int argc, char *argv[]) {
if (argc < 2) return 1;
char * filename = argv[1];
FILE* file = fopen(filename, "r");
if(file == NULL) {
perror("Error opening file");
return(1);
}
char c;
while((c = fgetc(file)) != EOF)
{
if(c == ' ' || c == '\n')
{
printf("\n");
}
else
{
printf("%c", c);
}
}
printf("Done.");
fclose(file);
return 0;
}
So far it has returned nothing, and doesn't show an error. The command line looks like this:
C:\Users\<USERNAME>\Desktop\C_C++>program.exe < file.txt
C:\Users\<USERNAME>\Desktop\C_C++>program.exe > file.txt
C:\Users\<USERNAME>\Desktop\C_C++>
It's using a windows command line. I didn't know whether or not I had to use > or < when passing in a file parameter, but I've also just used the file's name in place of filename in FILE* file = fopen(filename, "r"); to just open it directly instead of passing the filename as a parameter, but nothing shows.
I have no idea what is going wrong.
fgetc() returns int, not char. You need to declare
int c;
Otherwise, there's a possibility that the test for EOF will never succeed.
Your program expects the filename as a command-line argument, it doesn't read from standard input. So you have to give the filename as an argument, not use input redirection. The program is exiting immediately because argc is 1.
program.exe file.txt
You should add an error message so you'll know this is the problem:
if (argc < 2) {
printf("Usage: %s filename\n", argv[0]);
return 1;
}
I'm trying to solve this question regarding moving data from a file to another in C. Running the program gives a segmentation error 11. I've attached a picture of the question. Exercise 4
I believe there is a problem in opening the files, I entered inside the terminal the C code script name: code.c file1.txt file2.bin -b. The files are included in the path.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char** argv){
size_t k;
char read1[100] = {};
FILE* s;
FILE* d;
if (argc < 4) {
printf("NA");
exit(1);
}
if (strcmp(argv[4], "-b") == 0) {
printf("binary file output\n");
d = fopen(argv[3], "wb");
if (d == NULL) {
printf("cant open d");
exit(1);
}
} else {
if (strcmp(argv[4], "-t") == 0) {
printf("textual file output\n");
d = fopen(argv[3], "w");
} else {
printf("error");
exit(1);
}
}
s = fopen(argv[2], "r");
if (s == NULL) {
printf("cant open s");
exit(2);
}
k = fread(read1, sizeof(char),100, s);
while (k != 0) {
fwrite(read1, k,1, s);
k = fread(read1, sizeof(char),100, s);
}
fwrite(read1, k,1, s);
fclose(s);
fclose(d);
return 1;
}
I expect to move all the data from file 1 to file 2, and file2 output can be binary or textual depending on the user input stream. Ignored the 'hexadecimal' case.
You seem to want to write a program that takes the name of an input file, an output file and a flag (-b or -t), so I guess you're calling your program like this:
program infile outfile [-b|-t]
Those are 3 arguments. They will be argv[1], argv[2] and argv[3] respectively. You should not access argv[4]. Your program will segfault on strcmp(argv[4], "-b"). All your argv[x] should be shifted back by one. The check if (argc < 4) is ok though.
Another thing that can cause segmentation fault is reading from a FILE* that is not valid. You're not checking if d == NULL after the second fopen(). You should do that, and exit with an error in case it's NULL.
Other than this, other problems with your code are:
You should not call fwrite after exiting the while loop. You know that k == 0 when out of the loop. It is not harmful, but it's useless and will print nothing.
You should reorder the arguments of fwrite like this: fwrite(read1, 1, k, s).
Your last return 1 statement makes no sense, you should return 0, not 1, for sucessful program execution.
You don't need to initialize the array with char read1[100] = {}; since you don't use it before overwriting its content. Doing char read[100]; is just fine.
PS: you should learn to use GDB to debug your programs. Problems like this one are very easy to spot using GDB by just stepping through the instructions one by one.
The following code compiles with no error or warnings, I can also execute the program and it will act as expected in that it will return the error messages at locations it is expected, for example, providing arguments to non-existent files. This lets me know the code is working as far as line 28 (close of the !fpc section)
Meaning there must be an issue from the
register int ch, i;
Down to
return (1);
before
printf("\"%s\"\n",line);\
The program is expected to take command line arguments of the program name itself and two file names, it then opens both of these files, and should then copy strings from the first file up to a max length to the second file while adding " to both the start and end of the string in the new file.
The code I have is
fgetline.c
#include "fgetline.h"
int main(int argc, char *argv[]) {
if (argc != 3) {
printf("usage: enquote filetocopy filetowrite \n");
exit(1);
}
fp = fopen(argv[1], "r");
if (!fp) {
printf("Couldn't open copy file: (%d) %s\n", errno, strerror(errno));
return -1;
}
fpc = fopen(argv[2], "r+");
if (!fpc) {
printf("Couldn't open write file: (%d) %s\n", errno, strerror(errno));
return -1;
}
register int ch, i;
ch = getc(fp);
if (ch == EOF)
return -1;
i = 0;
while (ch != '\n' && ch != EOF && i < max) {
line[i++] = ch;
ch = getc(fp);
}
line[i] = '\0';
while (ch != '\n' && ch != EOF) {
ch = getc(fp);
i++;
}
return(i);
printf("\"%s\"\n",line);
fclose(fp);
fclose(fpc);
return 0;
}
fgetline.h
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
int fgetline(FILE *fp, char *line, int max);
FILE *fp, *fpc;
#define max 30
char line[max + 1];
I am compiling with
debian:~/uni/Ass0$ gcc fgetline.c -Wall -o enquote
debian:~/uni/Ass0$ cd /
testing I did was
debian:~/uni/Ass0$ ./enquote
usage: enquote filetocopy filetowrite
debian:~/uni/Ass0$ ./enquote test
usage: enquote filetocopy filetowrite
debian:~/uni/Ass0$ ./enquote test frog
Couldn't open write file: (2) No such file or directory
debian:~/uni/Ass0$ ./enquote monkey frog
Couldn't open copy file: (2) No such file or directory
debian:~/uni/Ass0$ cat test
ting
test
123
tim#debian:~/uni/Ass0$ cat test2
tim#debian:~/uni/Ass0$ ./enquote test test2
tim#debian:~/uni/Ass0$ cat test2
expected result would be when I run ./enquote test test2, would copy
ting
test
123
from test to test2 so it would appear like
"ting"
"test"
"123"
Thanks, not sure how much more info to give.
There are many issues with your code, compiling with all warnings enabled would have spotted some of them:
Declaring global variables in a header file is good practice, but not defining them there. The extern keyword is used for declarations. The definitions belong in the C file. In this case, variables such as fp, fp1, line should be defined as local variables, not global variables.
Output file argv[2] should be open with "w" mode, "r+" is used for updated mode and will fail if the file does not exist. Update mode is very tricky and confusing, avoid using it.
Do not use the register keyword, it is obsolete now as compilers are smart enough to determine how to best use registers.
Your while loops will read just 2 lines from the input file, storing the first into the line array and discarding the second one.
The return (i); statement exits the program, no output is performed, the remaining statements in the function are ignored completely (-Wall might have spotted this error).
You can simplify the problem by considering this: You want to output a " at the beginning of each line and before the '\n' at the end of each line. You do not need to buffer the line in memory, which would impose a limit on line length. Just output the " whenever you start a line and before you end one:
#include <errno.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
FILE *fp, *fpc;
int ch, last;
if (argc != 3) {
printf("usage: enquote filetocopy filetowrite\n");
exit(1);
}
fp = fopen(argv[1], "r");
if (!fp) {
fprintf(stderr, "Could not open input file: (%d) %s\n",
errno, strerror(errno));
return 2;
}
fpc = fopen(argv[2], "w");
if (!fpc) {
fprintf(stderr, "Could not open output file: (%d) %s\n",
errno, strerror(errno));
return 2;
}
last = '\n'; // we are at the beginning of a line
while ((ch = fgetc(fp)) != EOF) {
if (last == '\n') {
fputc('"', fpc); // " at the beginning of a line
}
if (ch == '\n') {
fputc('"', fpc); // " at the end of a line
}
fputc(ch, fpc);
last = ch;
}
if (last != '\n') {
// special case: file does not end with a \n
fputc('"', fpc); // " at the end of a line
fputc('\n', fpc); // put a \n at the end of the output file
}
fclose(fp);
fclose(fpc);
return 0;
}
Right now, I have something like this...
CMD console window:
c:\users\username\Desktop> wrapfile.txt hello.txt
Hello
How would I get something like this?
CMD console window:
c:\users\username\Desktop> wrapfile.txt hello.txt hi.txt
Hello Hi
with this code?
#include <stdio.h>
#include <stdlib.h>
int main(int argc[1], char *argv[1])
{
FILE *fp; // declaring variable
fp = fopen(argv[1], "rb");
if (fp != NULL) // checks the return value from fopen
{
int i;
do
{
i = fgetc(fp); // scans the file
printf("%c",i);
printf(" ");
}
while(i!=-1);
fclose(fp);
}
else
{
printf("Error.\n");
}
}
Well, first of all: in your main declaration, you should use int main(int argc, char* argv[]) instead of what you have right now. Specifying an array size makes no sense when declaring an extern variable (that's what argv and argc are). On the top of that, you are not using the correct types. argc is integer and argv is array of strings (which are arrays of chars). So argv is an array of arrays of chars.
Then, simply use the argc counter to loop through the argv array. argv[0] is the name of the program, and argv[1] to argv[n] will be the arguments you pass to your program while executing it.
Here is a good explanation on how this works: http://www.physics.drexel.edu/courses/Comp_Phys/General/C_basics/#command-line
My 2 cents.
EDIT: Here is a commented version of the working program.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
FILE *fp;
char c;
if(argc < 3) // Check that you can safely access to argv[0], argv[1] and argv[2].
{ // If not, (i.e. if argc is 1 or 2), print usage on stderr.
fprintf(stderr, "Usage: %s <file> <file>\n", argv[0]);
return 1; // Then exit.
}
fp = fopen(argv[1], "rb"); // Open the first file.
if (fp == NULL) // Check for errors.
{
printf("Error: cannot open file %s\n", argv[1]);
return 1;
}
do // Read it.
{
c = fgetc(fp); // scans the file
if(c != -1)
printf("%c", c);
} while(c != -1);
fclose(fp); // Close it.
fp = fopen(argv[2], "rb"); // Open the second file.
if (fp == NULL) // Check for errors.
{
printf("Error: cannot open file %s\n", argv[2]);
return 1;
}
do // Read it.
{
c = fgetc(fp); // scans the file
if(c != -1)
printf("%c", c);
} while(c!=-1);
fclose(fp); // Close it.
return 0; // You use int main and not void main, so you MUST return a value.
}
I hope it helps.
argv[2] would be the second file name.
Do not forget to check the value of argc to see if enough arguments are valid.
Better: use boost::program_options.
Caution: this code is not unicode-aware on Windows system, which makes it not portable. Refer to utf8everywhere.org about how to make it support all file names on this platform.