I am trying to pass a string into a function in C. That string will entered by the user and then passed on to the function to write to a text file. Iknow this seems very basic but I am just learning C.
#include <stdio.h>
#include <string.h>
void read() {
char text[50][30],buffer[150];
int i=0;
FILE *file_in;
file_in=fopen("test.txt","r");
if (file_in == NULL) {
printf("Error opening file\n");
}
while (fgets(buffer,150,file_in)) {
strcpy(text[i],buffer);
printf("line %d: %s\n",i,text[i]);
i++;
}
getchar();
fclose(file_in);
}
void write(char str[])
{
FILE *file_in;
file_in=fopen("test.txt","a");
if (file_in == NULL) {
printf("Error opening file\n");
}
//write to the file
fprintf(file_in, "\n%s", str);
// fputs(str, file_in);
fclose(file_in);
}
int main()
{
read();
char msg[50];
printf("Enter some text: ");
puts(msg);
write(msg);
return 0;
}
It writes to the file, but it writes weird characters, not what I actually type. What amI doing wrong?
It looks like you've confused gets with puts. puts writes a string to the console. gets reads a string from the console. Switch them out and your program should work.
Microsoft's compiler often warns against insecure or deprecated functions, like gets. You may use fgets instead, as it doesn't allow buffer overflows.
Here's an example:
fgets(msg, 50, stdin);
or
fgets(msg, sizeof(msg), stdin);
First of all: Don't call your functions read() and write() — pick something more specific. The function names read() and write() are already used by the system for low-level file operations, and trying to define them yourself will cause unexpected behavior.
Second: you are never initializing the contents of the msg variable or reading any data into it, so its contents will be random. (Remember that puts() prints data; it doesn't read anything.)
When you write char msg[50];, it contains indeterminate values. It's not zero-initialized or anything.
The puts(msg); line writes this garbage out, and then write(msg); writes that garbage to a file.
I guess you intended to have some code for inputting text, after the printf and before the puts.
NB. In your read() function (which you don't call yet), you should make the fgets buffer size match the width of your array , and you should check you don't run off the end of your array if the file has many lines.
Also it would be wise to name your functions something other than read and write, because in a POSIX environment there are already functions by that name which may clash.
Here is the solution:
#include <stdio.h>
#include <string.h>
int read() {
char text[50][30],buffer[150];
int i=0;
FILE *file_in;
file_in=fopen("test.txt","r");
if (file_in == NULL) {
printf("Error opening file\n");
}
while (fgets(buffer,150,file_in)) {
strcpy(text[i],buffer);
printf("line %d: %s\n",i,text[i]);
i++;
}
// getchar();why you were using this?
fclose(file_in);
// return 0;
}
void write(char str[])
{
FILE *file_in;
file_in=fopen("test.txt","a");
if (file_in == NULL) {
printf("Error opening file\n");
}
//write to the file
fprintf(file_in, "\n%s", str);
// fputs(str, file_in);
fclose(file_in);
}
int main()
{
char msg[50];
read();
printf("Enter some text: ");
// getchar();
gets(msg);//It reads in msg
write(msg);
return 0;
}
Related
Could you help me with the creation of a text file as right now the *fp pointer to the file is returning NULL to the function fopen ?
Using the library errno.h and extern int errno I get "Value of errno: 22".
if (!fp)perror("fopen") gives me "Error opening file: Invalid argument".
In my main function I enter the name of the file:
void main()
{
float **x;
int i,j;
int l,c;
char name_file[30];
FILE *res;
/* some lines omitted */
printf("\nEnter the name of the file =>");
fflush (stdin);
fgets(name_file,30,stdin);
printf("Name of file : %s", name_file);
res=creation(name_file,l,c,x);
printf("\nThe created file\n");
readfile(res,name_file);
}
The function to create the text file:
FILE *creation(char *f_name,int l, int c, float **a) // l rows - c colums - a array
{ FILE *fp;
int i,j;
fp = fopen(f_name,"wt+"); // create for writing and reading
fflush(stdin);
/* The pointer to the file is NULL: */
if (!fp)perror("fopen"); // it's returning Invalid argument
printf("%d\n",fp); //0 ??
if(fp==NULL) { printf("File could not be created!\n"); exit(1); }
fflush(stdin);
for(i=0;i<l;i++)
{
for(j=0;j<c;j++)
{
fprintf(fp,"%3.2f",a[i][j]); // enter every score of the array in the text file
}
fprintf(fp,"\n");
}
return fp;
}
Function to read the file and check if it is correct:
**void readfile(FILE *fp,char *f_name)**
{
float a;
rewind(fp);
if(fp==NULL) { printf("File %s could not open\n",f_name); exit(1); }
while(fscanf(fp,"%3.2f",&a)!= EOF)
printf("\n%3.2f",a);
fclose(fp);
}
There are quite a few wrong things your code.
1.
The correct signatures of main are
int main(void);
int main(int argc, char **argv)
int main(int argc, char *argv[])
See What are the valid signatures for C's main() function?
2.
The behaviour of fflush(stdin) is undefined. See Using fflush(stdin).
fflush works with output buffers, it tells the OS that is should write
the buffered content. stdin is an input buffer, flushing makes no sense.
3.
Use fgets like this:
char name_file[30];
fgets(name_file, sizeof name_file, stdin);
It's more robust using sizeof name_file because this will give you always
the correct size. If you later change the declaration of name_file to
an char array with less than 30 spaces, but forget to change the size parameter in fgets, you
might end up with a buffer overflow.
4.
You are passing to creation the uninitialized pointer p that is pointing
to nowhere. In said function you cannot read nor write with the pointer a.
You need to allocate memory prior to the call of creation. At least judging
from the code you posted.
5.
fgets preserves the newline ('\n') character, so
name_file is containing the newline character. I really don't know if newline
is allowed in file names. I did a google search but found conflicting answers.
I don't think that you want to have newlines in your file names, anyway. It's
best to remove it before passing it to fopen (which might be the reason for
the error 22):
char name_file[30];
fgets(name_file, sizeof name_file, stdin);
int len = strlen(name_file);
if(name_file[len - 1] == '\n')
name_file[len - 1] = 0;
My goal is to be able to write a string to a file and have the whole thing show up, and not just part of it. The problem is that when i check into my text file there is a few charters left off of the string that i typed in.
Here is My code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fp = fopen("file.txt", "w");
if (fp == NULL)
{
printf("Error opening file!\n");
exit(1);
}
char comment[100];
fp=fopen("/home/matthew/Desktop/BBE.txt","w");
printf("Enter, String: ");
scanf("%s", &comment);
fgets(comment, sizeof comment, stdin);
fputs(comment,fp);
}
And the input that i want in my text file is this:
Enter, String: Hello World
But when i check my text file i get this:
World
I am missing a word here and have no idea why, please help.
Get rid of the scanf, as it is reading in the first word of your input, so your code looks like this:
char comment[100];
fp=fopen("/home/matthew/Desktop/BBE.txt","w");
printf("Enter, String: ");
fgets(comment, sizeof comment, stdin);
fputs(comment,fp);
You are reading the input from the user using both fgets and scanf. You don't need both. Also, in your scanf, you are passing the address of the address of the first element of the character array instead of just the address of the first element (use 'comment' instead of '&comment' in your scanf). You are also not closing the File after write. Try following:
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fp = fopen("/home/matthew/Desktop/BBE.txt", "w");
if (fp == NULL)
{
printf("Error opening file!\n");
exit(1);
}
char comment[100];
fp=fopen("file.txt","w");
printf("Enter, String: ");
scanf("%s", comment); //Don't pass &comment. Just pass 'comment' - the addr of zeroth element.
//fgets(comment, sizeof comment, stdin);
fputs(comment,fp);
fclose(fp);
}
Why are you using two files here when you've to write the input from stdin in one of the file? Below piece of code will help you get the desired output. Better to use gets() here instead of fgets() as you're not reading input from file. Also, don't forget to close the files when you're done. Hope this helps!!
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
FILE *fp;
char comment[100] = {0};
fp=fopen("tempfile.txt","w");
if (fp == NULL)
{
printf("Error opening file!\n");
exit(1);
}
printf("Enter String: ");
gets(comment);
fwrite(comment, sizeof(comment), 1, fp) ;
fclose(fp);
return 0;
}
This is making me nuts I am trying to make a simple program to copy any type of file using the following code but the result I get is unexpected (one or two extra characters at the end of copied file?). For instance if my original file has This is an example the copied file contains This is an exampleÿ
CODE
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fp,*fpp;
char pbuff, fname[32];
int i;
printf(" FILE NAME TO OPEN : ");
scanf(" %32s", fname);
fp = fopen(fname, "rb");
fpp = fopen("file", "wb");
if(fp==NULL)
{
printf("NO SUCH FILE. EXITING NOW.");
getch();
exit(1);
}
while(!feof(fp))
{
pbuff = fgetc(fp);
fputc(pbuff, fpp);
}
printf("SUCCESSFULLY CREATED!");
fclose(fp);
fclose(fpp);
getch();
return(0);
}
Can anyone help me out with this one? I will be really very thankful.
The reason is that feof (like most end-of-file indicators in most languages/environments) is only set AFTER the end-of-file has been reached. Since you write the character and only then check the EOF status, you're writing 1 too many characters. fgetc's return value is a predefined EOF if the end-of-file was reached during the call.
You could solve that in 1 of 2 ways:
while(true)
{
pbuff = fgetc(fp);
if(feof(fp))
break;
fputc(pbuff, fpp);
}
Or: (edit as melpomene correctly noticed!)
// Change pbuff to type int in the declartion, and then...
while(true)
{
pbuff = fgetc(fp);
if(EOF == pbuff)
break;
fputc(pbuff, fpp);
}
I have to write a program witch reads from a file received by line and then it overwrites it with the read words uppercased.
This is my code
void toUpperCase(char* string) {
int i=0;
while(string[i])
{
string[i]=toupper(string[i]);
i++;
} }
int main(int argc, char** argv) {
if(argc==1)
{
puts("Error: INSERT PATH");
exit(0);
}
char* file=argv[1];
FILE* fd=fopen(file,"r+");
if(fd<0)
{
perror("Error opening file: ");
exit(0);
}
char buffer[30][30];
int i=0;
while(!feof(fd))
{
fscanf(fd,"%s",buffer[i]);
i++;
}
int j=0;
for(j=0; j<i; j++)
{
toUpperCase(buffer[j]);
fwrite(buffer[j],strlen(buffer[j]),1,fd);
}
fclose(fd);
return 0; }
but this program appends the words contained in buffer[][] instead of overwriting the file.
If the file contain was something like pippo pluto foo then, after the execution is pippo pluto fooPIPPOPLUTOFOO instead of PIPPO PLUTO FOO.
Where am i wrong? Thank you
You have to reset the file position indicator using fseek, as fscanf will advance it. Something like
fseek(fd, length_of_read_string, SEEK_CUR);
This allows you to read the file in chunks, but it will be tricky to get right. Or of course reset it to the file start because you read everything in 1 go:
fseek(fd, 0L, SEEK_SET);
I strongly recommend writing the modified data into a new file, and then after the program has run, delete the initial file and rename the new one. That will also take care of another issue with your program, you are reading the entire file into memory before handling it.
If you want to do in-place translation that doesn't change lengths, you can open the source file in two streams and then do read-chunk, write-chunk in lockstep. That has the advantage of being super-easy to convert to a non-in-place version that will work with nonseekable files too (stdin/stdout, pipes, and sockets).
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <ctype.h> //toupper
inline void upcaseStr(char* str){
for(;*str;str++) { *str=toupper(*str); }
}
int upcaseStream(FILE* in, FILE* out){
char buf[BUFSIZ]; //BUFSIZ is an implementation-defined constant for an optimal buffer size
while(fgets(buf, BUFSIZ, in)){
upcaseStr(buf);
if(fputs(buf, out) == EOF){ return 1; }
}
if(!feof){ return 1; }
return 0;
}
int main(int argc, char **argv)
{
//default in and out
FILE* in = stdin;
FILE* out = stdout;
if(argc == 2) {
in = fopen(argv[1], "r"); //for reading
out = fopen(argv[1], "r+"); //for writing (and reading) starting at the beginning
if(!(in && out)){
fprintf(stderr, "Error opening file %s for reading and writing: %s\n", argv[1], strerror(errno));
}
}
return upcaseStream(in, out);
}
If you do use the in-place version, then in the unlikely event that the if(fputs(buf, out) == EOF){ return 1; } line should return, you're screwed unless you have a backup copy of the file. :)
Note:
You shouldn't name your FILE pointers fd because C people will tend to think you mean "file descriptor". FILE is a struct around a file descriptor. A file descriptor is just an int that you can use for FILE access with the raw system calls. FILE streams are an abstraction layer on top of file descriptors--they aren't file descriptors.
As you read from the file, its internal position indicator gets moved. Once you start writing, you start writing from that position on, which happens to be at the end of the file. So you effectively append the data to the file.
Rewind the handle to reset the position indicator before writing into the file:
rewind(fp);
On a side note, you are reading the file incorrectly:
while(!feof(fd))
{
fscanf(fd,"%s",buffer[i]);
i++;
}
When you reach the end of the file, fscanf will return an error and not read anything, yet you still increment variable i, as if the read was successful. And then you check feof() for end-of-file, but i was already incremented.
Check feof() and return of fscanf() immediately after calling fscanf():
while(1)
{
int read = fscanf(fd,"%s",buffer[i]);
if( read != 1 )
//handle invalid read
if( feof(fd) )
break;
i++;
}
Think about what happens if the string is longer than 29 characters and/or the file contains more than 30 strings. char buffer[30][30];
Welcome to StackOverflow!
Reopening the stream with fopen with the "w" parameter:
fd=fopen(file, "w");
It opens the file and if there are any contents in the file, it clears them.
this is my first question asked on here so if I'm not following the formatting rules here please forgive me. I am writing a program in C which requires me to read a few lines from a file. I am attempting to put each line into a cstring. I have declared a 2D character array called buf which is to hold each of the 5 lines from the file. The relevant code is shown below
#include <stdlib.h>
#include <sys/types.h>
#include <sys/file.h>
#include <sys/socket.h>
#include <sys/un.h> /* UNIX domain header */
void FillBuffersForSender();
char buf[5][2000]; //Buffer for 5 frames of output
int main()
{
FillBuffersForSender();
return 0;
}
void FillBuffersForSender(){
FILE *fp;
int line = 0;
char* temp = NULL;
size_t len = 0;
ssize_t read;
fp = fopen("frames.txt", "r");
printf("At the beginning of Fill Buffers loop.\n");
//while ((read = getline(&temp, &len, fp)) != -1){
while(line < 5){
//fprintf(stderr, "Read in: %s\n", temp);
fgets(temp, 2000, fp);
strcpy(buf[line], temp);
line++;
fprintf(stderr, "Line contains: %s.\n", temp);
temp = NULL;
}
while(line != 0){
fprintf(stderr, "Line contains: %s.\n", buf[line]);
line--;
}
}
The line
strcpy(buf[line], temp);
is causing a segmentation fault. I have tried this numerous ways, and cannot seem to get it to work. I am not used to C, but have been tasked with writing a bidirectional sliding window protocol in it. I keep having problems with super basic issues like this! If this were in C++, I'd be done already. Any help anyone could provide would be incredible. Thank you.
temp needs to point to an allocated buffer that fgets can write into.
In C programming, error checking is an important part of every program (in fact sometimes it seems like there's more error handling code than functional code). The code should check the return value from every function to make sure that it worked, e.g. if fopen returns NULL then it wasn't able to open the file, likewise if fgets returns NULL it wasn't able to read a line.
Also, the code needs to clean up after itself. For example, there is no destructor that closes a file when the file pointer goes out of scope, so the code needs to call fclose explicitly to close the file when it's finished with the file.
Finally, note that many of the C library functions have quirks that need to be understood, and properly handled. You can learn about these quirks by reading the man pages for the functions. For example, the fgets function will leave the newline character \n at the end of each line that it reads. But the last line of a file may not have a newline character. So when using fgets, it's good practice to strip the newline.
With all that in mind, the code should look like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXLINE 5
#define MAXLENGTH 2000
static char buffer[MAXLINE][MAXLENGTH];
void FillBufferForSender(void)
{
char *filename = "frames.txt";
FILE *fp;
if ((fp = fopen(filename, "r")) == NULL)
{
printf("file '%s' does not exist\n", filename);
exit(1);
}
for (int i = 0; i < MAXLINE; i++)
{
// read a line
if (fgets( buffer[i], MAXLENGTH, fp ) == NULL)
{
printf("file does not have %d lines\n", MAXLINE);
exit(1);
}
// strip the newline, if any
size_t newline = strcspn(buffer[i], "\n");
buffer[i][newline] = '\0';
}
fclose(fp);
}
int main(void)
{
FillBufferForSender();
for (int i = 0; i < MAXLINE; i++)
printf("%s\n", buffer[i]);
}
Note: for an explanation of how strcspn is used to strip the newline, see this answer.
When it comes to C you have to think of the memory. Where is the memory for a point with NULL assigned to it? How can we copy something to somewhere that we have no space for?