I have to solve the following problem in C for the operating systems class:
At the command line three file are given, two for input, one for output.
The output file is obtained from input files, as follows: 10 bytes from
the first file, 20 bytes from the second file, next 10 bytes from the
first file, next 20 bytes from the second file and so on, until
an input file is finished.
Simple but inefficient solution: read and write groups of 10 / 20 bytes.
An efficient (but not simple) solution: read and write blocks
with 5000 bytes.
I tried this for the simple solution. But it doesn't work... Can anyone help me?
#include<stdio.h>
int main(int argc, char* argv[], char* envp[]){
if (argc != 4){
printf("%s", "Usage: c4h filename\n");
return 0;
}
int c1,c2,i;
FILE *in1;
FILE *in2;
FILE *out;
in1 = fopen(argv[1], "r");
in2 = fopen(argv[2], "r");
out = fopen(argw[3], "wb");
if (in1 == NULL){
printf("%s", "File not found!\n");
return 0;
}
if (in2 == NULL){
printf("%s", "File not found!\n");
return 0;
}
while(feof(in1)!=0 && feof(in2)!=0){
for(int i=0;i<20;i++)
if(feof(in1)!=0){
c1 = fgetc(in1);
fputc(c1,out);
}
for(int i=0;i<10;i++){
if(feof(in2)!=0){
c2 = fgetc(in2);
fputc(c2,out);
}
}
fclose(in1);
fclose(in2);
fclose(out);
return 0;
}
There were three problems with your code:
Typo with argw instead of argv
Missing closing } for the while loop
feof(file)!=0 evaluates to true when you are at the eof, the exact opposite of the condition you want, replace with !eof(file) which evaluates to true only if you are not at eof
And one smaller problem, you redefine the variable i in your for loops: for(int i=0;i<10;i++) should be for(i=0;i<10;i++) since you define i earlier in the code.
You should try compiling your code before taking it to SO! The code you posted didn't even compile for me. Here's the working code:
#include<stdio.h>
int main(int argc, char* argv[], char* envp[]){
if (argc != 4){
printf("%s", "Usage: c4h filename\n");
return 0;
}
int c1,c2,i;
FILE *in1;
FILE *in2;
FILE *out;
in1 = fopen(argv[1], "r");
in2 = fopen(argv[2], "r");
out = fopen(argv[3], "wb");
if (in1 == NULL){
printf("%s", "File not found!\n");
return 0;
}
if (in2 == NULL){
printf("%s", "File not found!\n");
return 0;
}
while(!feof(in1) && !feof(in2)){
for(i=0;i<20;i++)
if(!feof(in1)){
c1 = fgetc(in1);
fputc(c1,out);
}
for(i=0;i<10;i++){
if(!feof(in2)){
c2 = fgetc(in2);
fputc(c2,out);
}
}
}
fclose(in1);
fclose(in2);
fclose(out);
return 0;
};
Related
I am trying to read a file in C. First I am calculating the lines in the file:
int main(int argc, char* argv[])
{
if (argc < 2)
{
printf("No file specified");
exit(1);
}
FILE* pFile;
char currentCharacter;
int lines = 1;
pFile = fopen(argv[1], "r");
for (currentCharacter = getc(pFile); currentCharacter != EOF; currentCharacter = getc(pFile))
{
if (currentCharacter == '\n') lines++;
}
...
}
After calculating the lines in the file, I tried reading one by one, like this:
char currentLine[255];
for (int i = 1; i <= lines; i++)
{
fgets(currentLine, 255, pFile);
printf("%s\n", currentLine);
}
fclose(pFile);
But everytime I run it, I am getting this output:
²a
When I try to remove the for loop and place fgets() and printf() outside, it prints NOTHING
If you are wondering, here is the content of the file I am trying to read:
test.txt
test1
test2
test3
NOTE: The file is being successfully opened as it is counting the lines correctly.
As said in the comments, no need to count the lines. Just stop when there is nothing more to read. That is, when fgets returns NULL.
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char* argv[])
{
if (argc < 2)
{
printf("No file specified");
exit(1);
}
FILE* pFile = fopen(argv[1], "r");
if(pFile==NULL)
{
printf("File is not found");
exit(1);
}
char currentLine[256];
while(fgets(currentLine, 256, pFile))
{
printf("%s", currentLine);
}
return 0;
}
I know the segfault is located within the argv[y] but I don't understand why! I'm very new to UNIX and rusty on my C. Any help would be awesome. (printfs were a messy way to find where the segfault was!)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define PAGELEN 24
#define LINELEN 512
void do_more(FILE *);
int see_more();
int main(int argc, char *argv[])
{
FILE *fp;
int i;
int loc;
int x;
int y;
char buffer[LINELEN];
FILE *t;
FILE *out;
FILE *read;
for(i=1; i<argc; i++){
if(strcmp(argv[i], "-o") == 0)
loc = i;
else if((t = fopen(argv[i], "r")) != NULL){
x = i;
fclose(t);
}
else{
y = i;
}
}
if(loc != -1){
FILE *read;
printf("1");
read = fopen(argv[x], "r");
printf("2");
out = fopen(argv[y], "w");
printf("3");
while(fgets(buffer, LINELEN, read))
printf("4");
fputs(buffer, out);
printf("5");
fclose(read);
fclose(out);
}
}
As yano mentioned, some variables can be left uninitialized, which will cause the segmentation fault. Enable compiler warnings (-Wall for most compilers) and fix all warnings it gives.
Using getopt() as Fiddling Bits mentioned would be great.
Another issue with your code is the check for whether an argument is the input file or the output file is bad. If the input file doesn't exist, or there is already a file with the same name as the output file, the check gives the wrong answer. Here is a better approach to parsing arguments, if you couldn't use getopt():
const char *input_filename = NULL;
const char *output_filename = NULL;
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "-o") == 0) {
if (output_filename != NULL || i + 1 >= argc) {
fprintf(stderr, "Error parsing arguments: double use of -o or missing filename\n");
return 1;
}
output_filename = argv[++i];
} else {
if (input_filename != NULL) {
fprintf(stderr, "Error parsing arguments: more than one input specified\n");
return 1;
}
input_filename = argv[i];
}
}
if (input_filename == NULL || output_filename == NULL) {
fprintf(stderr, "Error parsing arguments: missing input and/or output filename\n");
return 1;
}
FILE *read = fopen(input_filename, "r");
// add error checking here as well
FILE *out = fopen(output_filename, "w");
// add error checking here as well
...
So you had a couple of problems x and y are not being assigned correctly, if you harcode argv[1] instead of argv[x] and argv[3] instead of argv[y] it works fine, strangely enough the segfault only occours if the file to write already exists.
so try: code sample
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define PAGELEN 24
#define LINELEN 512
void do_more(FILE *);
int see_more();
int main(int argc, char *argv[]) // ./main file.txt -o out.txt
{
FILE *fp;
int i;
int loc;
int x;
int y;
char buffer[LINELEN];
FILE *t;
FILE *out;
FILE *f; // <-- changed to avoid confusion
for(i=1; i<argc; i++){
if(strcmp(argv[i], "-o") == 0)
loc = i;
else if((t = fopen(argv[i], "r")) != NULL){
x = i;
fclose(t);
}
else{
y = i;
}
}
if(loc != -1){
printf("1");
f = fopen(argv[1], "r");// <-- argument 2
printf("2");
out = fopen(argv[3], "w");// <-- argument 4
printf("3");
while(fgets(buffer, LINELEN, f)){
printf("4");
fputs(buffer, out);
}
printf("5");
fclose(f);
fclose(out);
}
}
Since your arguments don't seem to change you can leave it like that or, if you'd like, correct the argument selection for opening.
The getopt mentioned in the comments is always a good option for this.
You still have to account for the errors when the argument input is incorrect, this will still cause errors, but I will leave that for you.
This question already has answers here:
Read from file or stdin
(6 answers)
Closed 2 years ago.
I have a program that calculates a lottery tickets (this tickets are in a file.txt), and writes the winners tickets in another file. I have a subfunction called evaluate_tickets(file, lottery_numers, winner....)
In shell I write: ./program arg1 arg2... (arg1, arg2 are text files i.e. file.txt)
But now, I want to do ./program < file.txt. The problem is that I don't know how to send the parameter "file" of evaluate_tickets because I receive information by stdin.
Define a stream pointer FILE *fp; to read to input file:
If you want the input to be read from a file, use fp = fopen(filename, "r"); to open the file and close the stream after processing with fclose(fp);.
If you want the input to be read from standard input, just assign fp = stdin; instead of using fopen().
Here is a short example:
#include <stdio.h>
int main(int argc, char *argv[]) {
FILE *fp;
int c, lines;
if (argc > 1) {
fp = fopen(argv[1], "r");
if (fp == NULL) {
fprintf(stderr, "cannot open %s\n", argv[1]);
return 1;
}
} else {
fp = stdin; /* read from standard input if no argument on the command line */
}
lines = 0;
while ((c = getc(fp)) != EOF) {
lines += (c == '\n');
}
printf("%d lines\n", lines);
if (argc > 1) {
fclose(fp);
}
return 0;
}
Here is the same example with a cleaner approach, passing stdin or an open FILE pointer to an ad hoc function. Note how it handles all command line arguments:
#include <stdio.h>
void count_lines(FILE *fp, const char *name) {
int c, lines = 0;
while ((c = getc(fp)) != EOF) {
lines += (c == '\n');
}
printf("%s: %d lines\n", name, lines);
}
int main(int argc, char *argv[]) {
FILE *fp;
if (argc > 1) {
for (int i = 1; i < argc; i++) {
fp = fopen(argv[i], "r");
if (fp == NULL) {
fprintf(stderr, "cannot open %s\n", argv[i]);
return 1;
}
count_lines(fp, argv[i]);
fclose(fp);
}
} else {
/* read from standard input if no argument on the command line */
count_lines(stdin, "<stdin>");
}
return 0;
}
I am trying to figure out why this is not printing, I am trying to print each letter from a text file that is inputted through command prompt, but I am just getting an empty output... What am I doing wrong, and why does this not work? I feel like this logically should work. Thanks.
int main(int argc, char *argv[]) {
FILE *fp;
int i;
for (i = 1; i < argc; i++) {
printf("%s\n", argv[i]);
fp = fopen(argv[i], "r");
while (!feof(fp)) {
puts(fp);
}
fclose(fp);
}
return 0;
}
You are attempting to print a file pointer:
puts(fp);
Read the manual of puts() -that's not what it takes.
To read char-by-char and print on the stdout, you can do:
int ch;
fp = fopen(argv[i], "r");
if (!fp) {
perror("fopen");
exit(1);
}
while((ch=fgetc(fp)) != EOF) {
putchar(ch);
}
flcose(fp);
Unless you are passing multiple file names as arguments, your outer loop doesn't make much sense.
Your program has multiple problems:
You do not test the return value of fopen(): the program invokes undefined behavior if any of the command line arguments cannot be opened as a stream for reading.
while(!feof(fp)) is incorrect. Read this: Why is “while ( !feof (file) )” always wrong?
puts(fp); is incorrect as fp is a FILE *, not a string. Use a loop to copy the file contents one byte at a time.
Here is a corrected version:
#include <errno.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
FILE *fp;
int i, c;
for (i = 1; i < argc; i++) {
fp = fopen(argv[i], "r");
if (fp == NULL) {
fprintf(stderr, "cannot open %s: %s\n", argv[i], strerror(errno));
} else {
printf("%s\n", argv[i]);
while ((c = getc(fp)) != EOF) {
putchar(c);
}
fclose(fp);
}
}
return 0;
}
int main(int argc, char *argv[]) {
FILE *fp;
int i;
char buff[128];
for (i = 1; i < argc; i++) {
printf("\n%s\n", argv[i]);
if(NULL == (fp = fopen(argv[i], "r"))){//check open file
perror("fopen");
continue;
}
while (fgets(buff, sizeof buff, fp)) {//read into buffer
fputs(buff, stdout);//print buffer (not add newline)
}
fclose(fp);
}
return 0;
}
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.