Cannot write to a .txt file using write() function in C - c

I wrote the following code in order to write some random characters to a text file:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
int main()
{
int input_f = open("./input.txt", O_CREAT | O_APPEND | O_RDWR ,0666);
int i;
for(i=0;i<50;i++)
{
int r = rand()%252;
printf("%d size of r: %d\n",i,sizeof(r));
write(input_f,r,sizeof(r));
printf("%d we just wrote %d which is %c\n",i,r,r);
}
close(input_f);
}
I looked for some solutions to do this
Maybe someone here knows how can I fix this?

write(input_f,r,sizeof(r));
should be
write(input_f, &r, sizeof(r));
The second parameter is the address of the buffer you want to send according to the man page.
Also you should check the return value of the function to be equal to sizeof r.

write(input_f,r,sizeof(r)); should be write(input_f,&r,sizeof(r)); because write takes a pointer to the data to be written, not the data directly.
Other then that you should be checking the result of the open call, and write calls they can fail.

You're calling write wrong.
If you'd included unistd.h, you would have gotten a prototype and the compiler would have corrected you.
write(input_f,&r,sizeof(r)); //the 2nd arg is a void const*
Also, size_t arguments to printf require "%zu", and you should be checking for errors.

Others have already said why it doesn't work
I just want to add that you should also write :
#include <unistd.h>
Or else you'll get warnings during compilation.

The write() function do not take an int as second parameter but a pointer (void *) on a buffer, and its length. It means you will have to convert your int into a string in a buffer first (with sprintf() for instance) and then output the buffer to the file (with write())

Related

Calling a function doesn't execute the print statement inside that function

Why is it that my first block of code doesn't output anything while the 2nd block does print out "hi"? I suspect that the program never goes into the test() function in the first block, but I don't know why that happens and how I should fix it.
P.S. I know that my codes don't really make any sense such as that the return value of the functions should be char *. This is because I haven't completed the function and I am still at the stage of testing what I have written. I think the return value of char * shouldn't be the reason for my problem, but do let me know if it is!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* test(char **strs, int strs_sz){
printf("%s", "hi");
}
int main(void){
char *arg[] = {"XX", "YY", "ZZ"};
char *all = test(arg, 1);
printf("%s\n", all);
free(all);
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* fcn(char **para){
printf("%s", "hi");
}
int main(void){
char *arg[] = {"XX", "YY", "ZZ"};
char *s = fcn(arg);
}
To sum up what was already explained in the comments and fill in some blanks:
When using standard C library functions to work with files (printf actually works with a file stdout), the data is first cached in memory, and only written to the actual file when some condition is met:
The file is closed
The file is fflushed.
The memory buffer is full
etc.
In case of stdout, this will happen when the \n character is printed or when your program exists and the file is closed.
However, in your first code snippet you try to dereference (use) a pointer all.
Since you did not write a return statement in your test function, it is impossible to predict what value will end up being stored in all.
So, your program most likely crashes unexpectedly, and thus the buffer never gets written to stdout.
You should never test incomplete functions!
At the very least, build up a skeleton code that makes the function legal, such as a dummy return statement.
Otherwise, you will encounter "undefined behavior", which is another way of saying your program will react in weird and unpredictable ways.

Multiple call of char[] returning function for immediately fprint

I look for a comfortable way of converting a custom type variable to char[] (string) for the purpose of immediate fprinting. Here is what I intend to do, yet still flawed.
#include <stdio.h>
#include <string.h>
char * toStr (int);
void main (void) {
printf("%s , %s , %s \n", toStr(1), toStr(2), toStr(3));
}
char * toStr (int z) {
static char oS[100];
sprintf(oS, "%d", z);
printf("Will return: %s\n", oS);
return oS;
}
This will display
Will return: 3
Will return: 2
Will return: 1
1 , 1 , 1
I see what the problem is here, printf seems to print the content of static char oS once for all three calls in its parameterlist. It does not evaluate each call exactely when it is needed in the format string. But i need the static (as one possible way) to make the content of oS available outside of toStr.
I feel like I am almost there, of corse I want the output
1 , 2 , 3
on screen. Is there a possiblility to get what I want, without having to mallocate and free every part or storing each return of toStr in a sepearate variable just to fprint them aftwerwards? Isn't it possible to fprint the return values of the same function multiple times in one call?
Local static variables are shared between all invocations of the function. That means all calls will use the same buffer and return the same pointer to the same string.
And since the evaluation order of arguments is not specified (I don't remember if it's implementation defined, undefined, or just simply not specified), then you don't know which will be the last call (which will be the call the decides which the contents of the array will have).
The only thing you do know is that all arguments must be evaluated before the actual call to the function is made. Arguments and expressions are not evaluated lazily.
The order of evaluation of function arguments is unspecified. So printf doesn't necessarily evaluate it in any order you desire/expect.
As you debug prints show, toStr does write multiple value to oS. But all arguments of printf will be evaluated before the function call is made.
So the whatever the value written as will be value written by printf for all 3 arguments since the function toStr returns the pointer to the same object (oS in toStr).
Note that function-local static variables are error prone as it's not thread-safe.
But i need the static (as one possible way) to make the content of oS available outside of toStr.
It's not possible to achieve what you want in your current way. You can either ask toStr to allocate memory each time (save it in the caller and free it after use).
Or pass the buffer you to write to each time:
#include <stdio.h>
#include <string.h>
char *toStr(char *, size_t, int);
int main (void)
{
char s1[256];
char s2[256];
char s3[256];
/* could also use s[3][256]; instead 3 separate vars */
printf("%s , %s , %s\n", toStr(s1, sizeof s1, 1), toStr(s2, sizeof s2, 2), toStr(s3, sizeof s3, 3));
}
char *toStr(char *oS, size_t len, int z)
{
snprintf(oS, len, "%d", z);
printf("Will return: %s\n", oS);
return oS;
}
After 3 calls to the function printf prarameters point to the same static buffer - and this buffer contains (which obvious only the one information.
You can check the evaluation order of your implementation without printfs inside the function
#include <stdio.h>
#include <string.h>
char *foo(const int i)
{
static char c[200] = {0,};
sprintf(&c[strlen(c)], "i = %d ", i);
return c;
}
int main(void) {
printf("%s %s %s\n", foo(1), foo(2), foo(3));
return 0;
}

Bad address error with execvp

I'm trying to make a shell "bosh>" which takes in Unix commands and keep getting a bad address error. I know my code reads in the commands and parses them but for some reason, I cannot get them to execute, instead, I get a "bad address" error.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <string.h>
#include <sys/wait.h>
#define MAX_LINE 128
#define MAX_ARGS 10
int main(){
pid_t pid;
char command[MAX_LINE]; /*command line buffer*/
char *commandArgs[MAX_ARGS]; /*command line arg*/
int i;
char *sPtr=strtok(command," ");
int n=0;
printf("bosh>");
fgets(command, MAX_LINE-1,stdin);
command[strlen(command)-1]='\0';
while(strcmp(command,"quit")!=0)
{
n=0;
sPtr=strtok(command," ");
while(sPtr&&n<MAX_ARGS)
{
sPtr=strtok(NULL," ");
n++;
}
commandArgs[0]=malloc(strlen(command)+1);
strcpy(commandArgs[0],command);
if(fork()==0)
{
execvp(commandArgs[0],commandArgs);
perror("execvp failed");
exit(2);
}
pid=wait(NULL);
printf("%s",">" );
fgets(command, MAX_LINE-1,stdin);
command[strlen(command)-1]='\0';
}
printf("Command (%d) done\n", pid);
return 0;
}
These two lines are the culprit:
commandArgs[0]=malloc(strlen(command)+1);
strcpy(commandArgs[0],command);
First of all, malloc(strlen(...)) followed by strcpy is what the POSIX function strdup already does. But then, you don't need to even copy the string - it is enough to just store the pointer to the original string into commandArgs[0]:
commandArgs[0] = command;
But then, how does execvp how many arguments the command is going to take? If you read the manuals carefully, they'd say something like:
The execv(), execvp(), and execvpe() functions provide an array of pointers to null-terminated strings that represent the argument list available to the new program. The first argument, by convention, should point to the filename associated with the file being executed. The array of pointers MUST be terminated by a NULL pointer.
Your argument array is not NULL-terminated. To fix it, use
commandArgs[0] = command;
commandArgs[1] = NULL; // !!!!
(Then you'd notice that you'd actually want to assign the arguments within the strtok parsing loop, so that you can actually assign all of the arguments into the commandArgs array; and compile with all warnings enabled and address those, and so forth).
You initialize sPtr in its declaration, which you do not need to do because you never use the initial value. But the initialization produces undefined behavior because it depends on the contents of the command array, which at that point are indeterminate.
The array passed as the second argument to execvp() is expected to contain a NULL pointer after the last argument. You do not ensure that yours does.
You furthermore appear to drop all arguments to the input command by failing to assign tokens to commandArgs[]. After tokenizing you do copy the first token (only) and assign the copy to the first element of commandArgs, but any other tokens are ignored.

Multiple reading from file fails (char array malloc required?)

I am experiencing that calling read_from_fd more than once causes the data to be empty.
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
int fd;
void read_from_fd() {
char data[2];
read(fd, data, 1);
data[1] = 0x00;
printf("data %s\n", data);
}
int main(void) {
fd = open("test.txt", O_RDWR);
read_from_fd();
read_from_fd();
read_from_fd();
}
So the first read prints data but the second and third one print something empty.
I guess this has to do something with the memory from char. Is this correct? What do I have to do to fix this?
Bodo
If there is only one character in the input, then it is clear that you will get it only once. This has to do with the seek pointer in the file. When you perform an open with the O_RDWR flag, the seek pointer is placed at the beginning of the file. Then on every call to read it is moved the amount of bytes read. When the seek pointer reaches the end of the file, the call to read will fill your buffer with 0 and return an appropriate value.
If you want to read the same character over and over, you have to reset the seek pointer using function lseek.
According to opengroup The behavior of multiple concurrent reads on the same pipe, FIFO, or terminal device is unspecified.

Writing to a file in a C (Linux). What's wrong?

2 days ago I've installed linux on my machine (1st time in my life :P) and now I'm tryin to write a char into a file. For some reason, it's not working... Here's my code.
#include <stdio.h>
#include <fcntl.h>
int main (int xd, char *tab[]) {
char *path1 = tab[1];
int filee = open(path1, O_WRONLY | O_CREAT| O_TRUNC, 0777);
write(filee, 'x', sizeof(char));
close(filee);
return 0;
}
What could be wrong in this little piece of code? I've checked and function 'write' returns -1, even though function 'open' creates the file when it doesnt exist.
Thanks.
write takes a pointer to a memory buffer as the second argument, but you pass it an int
write(filee,'x',sizeof(char));
You should try something along the lines of
char c = 'x';
write(filee, &c, sizeof(char));
You are passing a character literal where write() expects a pointer to the data.
Try something like this:
const char data[] = { 'x' };
write(fille, data, sizeof data);
Also, you should check the return value of open() before relying on the file descriptor being valid.
When using API:s you're not familiar with, it's a good idea to read the manual page, and check the expected arguments against what you are using.
Also, you should enable more compiler warnings; this is something the compiler should have warned about, for sure.

Resources