I am trying to convert strings and integers to binary using fscanf and fwrite to write them to an output file.
My input file:
a 100
ab 99
abc 98
abcd 97
abcde 96
Each space separating the string and int on each line is a tab.
Here is my main.c file where the magic should be happening (but is not):
#include <stdio.h>
#include <stdlib.h>
#define MAX_LEN 30
int main(int argc, char * argv[]){
FILE *ifp;
FILE *ofp;
if(argc != 4){
fprintf(stderr, "Usage: flag %s input-file output-file\n", argv[0]); exit(1);
}
if((ifp = fopen(argv[2], "r")) == NULL){ /* error check to make sure the input file is open*/
fprintf(stderr, "Could not open file: %s", argv[2]); exit(1);
}
puts("input file open\n");
if((ofp = fopen(argv[3], "wb")) == NULL){ /* Opens output file to write in binary*/
puts("couldnt open output file\n"); exit(1);
}
puts("output file open\n");
unsigned char tempstr[MAX_LEN];
unsigned int tempint;
while(fscanf(ifp, "%u %u\n",(unsigned int*)&tempstr, &tempint) == 2){
fwrite((const void*)&tempstr, sizeof(tempstr)+1, 1, ofp);
fwrite((const void*)&tempint, sizeof(unsigned int), 1, ofp);
puts("ran loop");
}
fclose(ifp);
return 0;
}
When I run my code my while loop does not seem to be running(ie.the "ran loop" is not being output). Not sure where to go from here?
Also my calls at the command line are as follows:
./a.out main.c t1.txt t1.bin
Any help would be appreciated! Thanks!
I believe this should get rid of the seg fault.
The type should be char * instead of unsigned char *
The array should have enough space to hold the required characters plus the null terminator.
.
char tempstr[30];
unsigned int tempint;
while (fscanf(ifp, "%s \t %i\n",tempstr, &tempint) == 2 ) {
fwrite((const void*)&tempstr, sizeof(tempstr)+1, 1, ofp);
fwrite((const void*)&tempint, sizeof(unsigned int), 1, ofp);
puts("ran loop");
}
Also I guess you don't need main.c, while executing ./a.out ... etc. You can change check for argc != 3 instead of 4 in your code.
Related
im working on my project to school and i run on this issue and cant continue forward. Can you plese help me? Im geting data from text document and and trying it save line by line to string array. When i printf data to stdin they are shown how they shuld be, but when i try it to printf them out of while function, conecent of all positions in array is last line of text document.
int main(int argc, char *argv[])
{
//Validate command line arguments
if (argc != 2) {
fprintf(stderr, "USAGE : %s file.txt\n", argv[0]);
return(1);
}
//Open text file for reading
FILE *f = fopen(argv[1], "r");
//Error exit if there was a problem opening the above file
if (f == NULL) {
fprintf(stderr, "Error opening file %s \n", argv[1]);
return(1);
}
int i = 0;
char *array[1000];
char line[500];
while (fgets(line, sizeof(line), f)) {
array[i]=line;
printf("%d",i);
printf("%s", array[i]);
i++;
}
printf("%s", array[1]);
printf("%s", array[2]);
printf("%s", array[3]);
printf("%s", array[4]);
fclose(f);
return 0;
}
Output:
0U 123456789101112131415161718192021222324252627282930
1S a b c x
2S x y z
3C intersect 2 3
4C minus 2 3C minus 2 3C minus 2 3C minus 2 3
Thnx guys <3
You need to allocate memory for each line you read. Currently you only have the one line[]. For example, change the line
array[i]=line;
to
array[i]=(char *)malloc(strlen(line)+1);
strcpy(array[i], line);
This will make allocate space for each string, and copy your line to it.
I had made a program in c in Ubuntu using gcc-7.I had sambleb.out file which is executable.I want to copy that file using c programming. here is the program.
#include <stdio.h>
int main()
{
FILE *fp;
fp = fopen("sampleb.out","rb");
FILE *fpcp;
fpcp = fopen("cp-of-sampleb.out","wb");
char forcp;
while (1)
{
forcp = fgetc(fp);
if(forcp == EOF)
break;
fputc(forcp, fpcp);
}
fclose(fp);
fclose(fpcp);
}
when I compile the program and execute the it, I get segmentation fault.
$ a.out && chmod a+x cp-of-sampleb.out
$ ./cp-of-sampleb.out
Segmentation fault
here is the content of cp-of-sample.out
$ cat cp-of-sampleb.out
ELF>0####8 ######��88#8###,, `` (
((`(`��TT#T#DDP�td##44Q�tdR�td``��/lib64/ld-
linux-x86-64.so.2GNU GNUX�T3�O���t�R�b�Ss�F
$
libc.so.6printf__libc_start_main__gmon_start__GLIBC_2.2.5ui
3�`` `H�H�%
H��t�CH��
and content of sampleb.out
$ cat sampleb.out
ELF>0####8 ######��88#8###,, `` (
((`(`��TT#T#DDP�td##44Q�tdR�td``��/lib64/ld-
linux-x86-64.so.2GNU GNUX�T3�O���t�R�b�Ss�F
$
libc.so.6printf__libc_start_main__gmon_start__GLIBC_2.2.5ui
3�`` `H�H�%
H��t�CH���5
�%
#�%
h������%
h������%�
]�8`��D]�fD�8`UH��8`H��H��H��H��?
H�H��t�H��tU�8`H=8`H��t�H��t
]�8`��]�fD�=a
uUH���~����O
]�D��#f.�UH��]��UH�忸#�������]�f.�DAWAVA��AUATL�% UH�-
SI��I��L)�H�H���g���H��t
1��L��L��D��A��H��H9�u�H�[]A\A]A^A_Ðf.���H�H��how are you I am
fine this singale line is printed by multiline
printf;4�����0���P����0��������zRx
�����*zRx
�$h���0FJ
U
�?;*3$"DW���A�C
Dd`���eB�B�E �B(�H0�H8�M#r8A0A(B BB�����#�#
�#` `���o�##�# �#
?
`0�#� ���o`#���o���oX#(`##GCC: (Ubuntu 7.1.0-
5ubuntu2~16.04) 7.1.08#T#t#�#�##X#`# �#
�#
�#
#0#�#�##8#` `(`�``(`8`��
`#�#!
�#78`F `m#y`������(#���(`(���`�(`(8`8�08)8h� P�
(I hadn't posted last line cause they were to many).Thus I can see that my program is coping only first 7 lines.It will be very helpful if you tell me what is wrong??? I am still noob.
First, any such program should check the result of fopen() before continuing. If you don't do this, you're potentially using a NULL pointer that's returned from fopen() in case of failure and your program will crash.
Your immediate problem is that you assign the return value of fgetc() to a char. fgetc() returns an int which either corresponds to the value of an unsigned char or is EOF, an int constant that is negative and distinct from any valid character.
What might happen when you compare EOF to a char is the following: Your char can be signed, so in a binary file, you could find a byte that is -1 with signed char. -1 is often used as the int (!) value of EOF, so your comparison will be true even though fgetc() did not return EOF.
Fix: Replace char forcp; with int forcp;.
That all said, it's very inefficient copying a file byte by byte. You should better use a buffer and fread()/fwrite() for copying, like in the following example that also adds proper error checking:
#include <stdio.h>
#define BUFFERSIZE 8192 // 8 kiB
int main(int argc, char **argv)
{
if (argc != 3)
{
fprintf(stderr, "Usage: %s source dest\n", argv[0]);
return 1;
}
FILE *src = fopen(argv[1], "rb");
if (!src)
{
fprintf(stderr, "Error opening %s for reading.\n", argv[1]);
return 1;
}
FILE *dst = fopen(argv[2], "wb");
if (!dst)
{
fclose(src);
fprintf(stderr, "Error opening %s for writing.\n", argv[2]);
return 1;
}
char buf[BUFFERSIZE];
int rc = 1; // <- failure
do
{
size_t nread = fread(buf, 1, BUFFERSIZE, src);
if (nread < BUFFERSIZE)
{
if (ferror(src))
{
fprintf(stderr, "Error reading from %s.\n", argv[1]);
goto done;
}
if (!nread) break;
}
if (fwrite(buf, 1, nread, dst) < nread)
{
fprintf(stderr, "Error writing to %s.\n", argv[2]);
goto done;
}
} while (!feof(src));
rc = 0; // <- success
done:
fclose(dst);
fclose(src);
return rc;
}
For an assignment I have to input text from 2 files line by line into a 3rd file. So file 1 line 1 would be file 3 line 1 and file 2 line would would be file 3 line 2. I have attempted to this but can not seem to get the lines from each file to alternate. I am only able to get lines from each file separately. Please help with any suggestions.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
FILE *file1, *file2, *file3;
char line [1000]; /* or other suitable maximum line size */
// check to make sure that all the file names are entered
if (argc != 4) {
perror("Error: ");
printf("Not enough files were entered!\n");
exit(0);
}
file1 = fopen(argv[1],"r");;
file2 = fopen(argv[2],"r");
file3 = fopen(argv[3],"w");
// check whether the file has been opened successfully
if (file1 == NULL)
{
perror("Error: ");
printf("Cannot open file1 %s!\n", argv[1]);
exit(-1);
}
// check whether the file has been opened successfully
if (file2 == NULL)
{
perror("Error: ");
printf("Cannot open file2 %s!\n", argv[2]);
exit(0);
}
// check whether the file has been opened successfully
if (file3 == NULL)
{
perror("Error: ");
printf("Cannot open file3 %s!\n", argv[3]);
exit(0);
}
int count = 0;
while (1)
{
if(fgets(line, sizeof line, file1) != NULL)
{
count+=1;
fprintf(file3, line);
}
else
{
break;
}
if(fgets(line, sizeof line, file2) != NULL)
{
count++;
fprintf(file3, line);
}
else
{
break;
}
}
fclose (file1);
fclose (file2);
fclose (file3);
}
fprintf(FILE *, const char *format, ...) expects a format as the 2nd argument.
Using fprintf(file3, line); will invoke undefined behavior (UB) should line contain a '%' or at least a missing % if "%%" was encountered.
Use fputs()
// fprintf(file3, line);
fputs(line, file3);
Additional concerns for advanced coding:
If the source file contains a null character, using fgets() is insufficient as it does not report the length read. Other approaches include using fgetc(), fread() or non-standard C getline().
If an input file does not end with a '\n', that rump line may look like a pre-fix to the line read from the other file.
As OP has noted, line length's of about 1000+ are a problem.
Source files line-endings, should they not match the code's understanding of line-ending can cause issues.
I want to copy the contents of file1 to file2 exactly as they are (keeping spaces and newlines). I specifically want to copy these contents one small block of chars at a time(this is a small segment of a larger project so bear with me).
I have attempted the following:
#include <stdio.h>
#include <stdlib.h>
#define MAX 5
int main(int argc, char *argv[]) {
FILE *fin, *fout;
char buffer[MAX];
int length;
char c;
if((fin=fopen(argv[1], "r")) == NULL){
perror("fopen");
exit(EXIT_FAILURE);
}
if((fout=fopen(argv[2], "w")) == NULL){
perror("fopen");
exit(EXIT_FAILURE);
}
while(1){
length = 0;
while((c = fgetc(fin)) != EOF && length < MAX){
buffer[length++] = (char) c;
}
if(length == 0){
break;
}
fprintf(fout, "%s", buffer);
}
fclose(fout);
fclose(fin);
}
However, this causes incorrect output to my file2. Any input would be appreciated.
Your buffer is not zero-terminated. Use fwrite instead of fprintf:
fwrite(buffer, 1, length, fout);
And you should check the error too. So compare return code of fwrite to length and if it differs, either retry the write of remaining bytes (if positive) or print appropriate error message via perror("fwrite") (if return code is negative).
Additionally you may consider opening the files in binary mode which would cause difference on windows, i.e. pass "rb" and "wb" to fopen.
Last but not least, instead of looping and getting one character at a time, consider using fread instead:
length = fread(buffer, 1, MAX, fin);
Here is a simple example.(with no error checking)
You should use fwrite() since the string you would write to file is not a "null-terminated". And also note that "b" mode is specified with fopen(), which means you want to open the file as a binary file.
#include <stdio.h>
#include <stdlib.h>
#define MAX 5
#define FILE_BLOCK_SIZE 50
int _tmain(int argc, _TCHAR* argv[])
{
FILE *fin, *fout;
unsigned char *BufContent = NULL;
BufContent = (unsigned char*) malloc(FILE_BLOCK_SIZE);
size_t BufContentSz;
if((fin=fopen("E:\\aa.txt", "rb")) == NULL){
perror("fopen");
exit(EXIT_FAILURE);
}
if((fout=fopen("E:\\bb.txt", "wb")) == NULL){
perror("fopen");
exit(EXIT_FAILURE);
}
while ((BufContentSz = fread(BufContent, sizeof(unsigned char), FILE_BLOCK_SIZE, fin)) > 0)
{
fwrite(BufContent, sizeof(unsigned char), BufContentSz, fout);
}
fclose(fout);
fclose(fin);
delete BufContent;
return 0;
}
First off, change char buffer[MAX]; to int buffer[MAX];, and char c; to int c;, for a char can be either signed char or unsigned char, depending on your implementation. In the later case, c = EOF will give c a large positive number(It's unsigned ,anyway), so the loop will never end. A int will be large enough to hold all characters and EOF though.
Then, change your
fprintf(fout, "%s", buffer);
to
fwrite(buffer, 1, length, four);
This is because fprintf(fout, "%s", buffer); call for a C-style string, with ends with a '\0', but your buffer isn't zero-terminated. As a result, the program will keep copying the stuff in the stack, until a '\0' is met, leaving lots of garbage in file2.
I am trying to print the remaining contents of a file after I do a fseek. Right now I am getting nothing returned. What's wrong with my code?
#include <stdio.h>
int main(int argc, char *argv[]){
FILE *fr;
if (fr = fopen (argv[1], "r")){
fseek(fr, 100, SEEK_CUR);
char c[1];
while (fread(c, 1, sizeof(c),fr) > 0)
printf("%s", c);
fclose(fr);
}
else{
perror("File does not exist");
}
}
As the other answers pointed out, you are passing printf a string which may not be NULL terminated. You are also not verifying the file being read is greater than 100 bytes. One last point, in fread() you swapped the size_t size and size_t niters parameters.
Here is an modified version of your program which fixes the above issues (and cleans up the spacing a bit):
#include <stdio.h>
#include <sys/stat.h>
int main(int argc, char *argv[])
{
FILE *fr;
char c[1];
struct stat sb;
// obtains information about the file
if (stat(argv[1], &sb) == -1)
{
perror("stat()");
return(1);
};
// verifies the file is over 100 bytes in size
if (sb.st_size < 101)
{
fprintf(stderr, "%s: file is less than 100 bytes\n", argv[1]);
return(1);
};
// opens the file, or prints the error and exists
if (!(fr = fopen (argv[1], "r")))
{
perror("fopen():");
return(1);
};
fseek(fr, 100, SEEK_CUR);
while (fread(c, sizeof(c), 1, fr) > 0)
printf("%c", c[0]);
fclose(fr);
return(0);
}
You could also improve the efficiency of reading the file by changing char c[1]; to something line char c[1024]; and updating the while statement to:
while (fread(c, sizeof(char), 1023, fr) > 0)
{
c[1023] = '\0';
printf("%s", c);
};
you cannot print with %s as your string needs to be null terminated and you only have one character.
use:
printf("%c",*c);
not all characters are printable, check an ascii table to see which are printable and which not. eg printing a 0 will not print anything on screen, AFAIK
You are reading a byte but trying to print it with %s, which expects a null-terminated string. Changing that to %c (and of course c to *c so that it agrees with the format string!) should fix things.
Especially if the value of the bytes you read is equal to 0, printf with the %s specifier will output absolutely nothing (as it thinks you are repeatedly asking it to print the empty string).
printf("%s",blabla) should print a null-terminated string. for print one char use printf("%c",c[0]).