My question is simple, I am a beginner in c language, I am currently developing the hangman game on code blocks. To do this a restriction was imposed on me, the file in which my word dictionary is located, I must pass it as an argument in my program. I saw in my research that in the project -> Set program's arguments .. tab, we can add arguments, but I cannot pass my text file as a parameter. Anyone have a solution please? thank you so much
I pass it like this :
But when I build my program it does not detect my file.
this is the code that tries to read the file
char *read_file(int ac, char **av, int *lifes, char **word)
{
int fd = -1;
int nb_caractere = 0;
char *buffer = calloc(1,sizeof(char));
if((fd = open(av[1], O_RDONLY)) == -1)
{
printf("Aucun fichier ou dossier. \n");
return (NULL);
}
lseek(fd, 0, SEEK_SET);
while(read(fd, buffer, 1) > 0)
{
nb_caractere++;
}
lseek(fd, 0, SEEK_SET);
buffer = calloc(nb_caractere+1, sizeof(char));
memset(buffer, 0, nb_caractere+1);
read(fd, buffer, nb_caractere);
close(fd);
return (buffer);
}
and the main how call this funtion is this :
int main(int ac, char **av)
{
int lifes = 10;
char *word = NULL;
char *hide_word = NULL;
srand(time(NULL));
if(ac < 2 || ac > 3)
{
printf("Nombres d'arguments incorrect !\n");
return (84);
}
if(ac == 3)
{
lifes = atoi(av[2]);
}
if(init_game(lifes, &word, &hide_word, read_file(ac, av, &lifes,
&word)) == 84 )
{
free(word);
return (84);
}
game_loop(lifes, word, hide_word);
free(word);
free(hide_word);
return 0;
}
the output of this code is "aucun fichier ou dossier"
Related
I managed to compile ncat. I am using -k option to keep server open. Instead of accepting data to STDOUT, my goal is to write to files instead. So far I was able to write to a file instead of STDOUT but my goal is to loop through new files on each new connection. Right now it is appending to the same filename_0 and f++ is not incrementing. Here is what I have so far. The original code will be below. The difference is in the else clause, basically if n is actually greater than 0. On each loop, n is 512 bytes until the last chunk. I just want to be able to have new files from each new connection. filename_0, filename_1, filename_3, etc.
MODIFIED CODE:
/* Read from a client socket and write to stdout. Return the number of bytes
read from the socket, or -1 on error. */
int read_socket(int recv_fd)
{
char buf[DEFAULT_TCP_BUF_LEN];
struct fdinfo *fdn;
int nbytes, pending;
int f = 0;
fdn = get_fdinfo(&client_fdlist, recv_fd);
ncat_assert(fdn != NULL);
nbytes = 0;
do {
int n, s;
n = ncat_recv(fdn, buf, 512, &pending);
if (n <= 0) {
if (o.debug)
logdebug("Closing fd %d.\n", recv_fd);
#ifdef HAVE_OPENSSL
if (o.ssl && fdn->ssl) {
if (nbytes == 0)
SSL_shutdown(fdn->ssl);
SSL_free(fdn->ssl);
}
#endif
close(recv_fd);
checked_fd_clr(recv_fd, &master_readfds);
rm_fd(&client_fdlist, recv_fd);
checked_fd_clr(recv_fd, &master_broadcastfds);
rm_fd(&broadcast_fdlist, recv_fd);
conn_inc--;
if (get_conn_count() == 0)
checked_fd_clr(STDIN_FILENO, &master_readfds);
return n;
}
else {
char filename[20];
snprintf(filename, sizeof(char) * 20, "filename_%i", f);
FILE *fp = fopen(filename, "a");
if (fp == NULL)
{
printf("Could not open file");
return 0;
}
//Write(STDOUT_FILENO, buf, n);
s = fwrite(buf, 1, n, fp);
fclose(fp);
f++;
nbytes += n;
}
} while (pending);
return nbytes;
}
ORIGINAL CODE:
int read_socket(int recv_fd)
{
char buf[DEFAULT_TCP_BUF_LEN];
struct fdinfo *fdn;
int nbytes, pending;
fdn = get_fdinfo(&client_fdlist, recv_fd);
ncat_assert(fdn != NULL);
nbytes = 0;
do {
int n;
n = ncat_recv(fdn, buf, sizeof(buf), &pending);
if (n <= 0) {
if (o.debug)
logdebug("Closing fd %d.\n", recv_fd);
#ifdef HAVE_OPENSSL
if (o.ssl && fdn->ssl) {
if (nbytes == 0)
SSL_shutdown(fdn->ssl);
SSL_free(fdn->ssl);
}
#endif
close(recv_fd);
checked_fd_clr(recv_fd, &master_readfds);
rm_fd(&client_fdlist, recv_fd);
checked_fd_clr(recv_fd, &master_broadcastfds);
rm_fd(&broadcast_fdlist, recv_fd);
conn_inc--;
if (get_conn_count() == 0)
checked_fd_clr(STDIN_FILENO, &master_readfds);
return n;
}
else {
Write(STDOUT_FILENO, buf, n);
nbytes += n;
}
} while (pending);
return nbytes;
}
I was able to figure out using the other functions involved. i passed a pointer into this function to write to it. the handler is a function i added the open() file pointer to.
This is supposed to flips upper and lower case letters but its not flipping just adding random characters.
int in = open(argv[1], O_RDONLY);
int out = open(argv[2], O_CREAT | O_WRONLY, 0624);
char buff[65];
buff[64] = '\0';
if(argc < 2){
printf("Not enough arguments");
return 1;
}
else if(argv[1] == 0 || argv[2] == 0){
printf("No file");
return 1;
}
int i = read(in,buff,64);
for (i = 0; buff[i]!='\0'; i++) {
if(buff[i] >= 'a' && buff[i] <= 'z') {
printf("%d", buff[i]-32);
} else if (buff[i] >= 'A' && buff[i] <= 'Z') {
printf("%d", buff[i]+32);
} else {
printf("%d", buff[i]);
}
}
write(out, buff, 64);
close(in);
close(out);
return 0;
}
How do I get it to read the character and flip without extras?
If your input file does not contain a '\0' as last character, your condition buff[i]!='\0' depends on random contents.
Change these lines:
char buff[65];
buff[64] = '\0';
to this line:
char buff[65] = { 0 };
However, read() tells you the number of bytes it read. You can use that value to mark the end:
int n = read(in,buff,64);
for (i = 0; i < n; i++) {
/* ... */
}
write(out, buff, n);
Write a function that reads a line, up to some maximum size; separate the logic of reading the file from other processing,
int readline(int fh, char* buff, int maxsize) {
int rc = read(fh,buff,maxsize);
if( rc < 0 ) {
printf("read error, %d\n",rc);
return rc;
}
return rc;
}
Write a function that writes the converted buffer, separate the logic of writing the file and other processing,
int writeline(int fh, char* buff, int len) {
int wc = write(fh, buff, len);
return wc;
}
Write a function that flips the case; separate the logic from reading and writing the file,
char* flipcase(char* buff, int len) {
if(!buff || len<1) return buff;
char* cp = buff;
for (int ix = 0; ix<len; ix++, cp++ ) {
if( isupper(*cp) { // in [A-Z]
// printf("%d", *cp-32); // not portable
*cp = tolower(*cp); // modify buff[ix]
}
else if( islower(*cp) ) { // in [a-z]
// printf("%d", *cp+32); // not portable
*cp = toupper(*cp); // modify buff[ix]
}
// else {
// unchanged
// }
// printf("%d", *cp);
}
return buff;
}
Build a function that handles each line separately,
# define MAXLINE (256) // named 'constant'
int doline(int fin, int fout) {
char buff[MAXLINE+1] = { 0 };
int rc = readline(fin, buff, MAXLINE);
// check results of readline here
flipcase(buff, rc);
int wc = writeline(fout, buff, rc);
// check results of writeline here
return rc;
}
Here you would handle your (argc, argv) and open your files,
if(argc < 3) {
printf("Not enough arguments");
return 1;
}
if(argv[1] == 0 || argv[2] == 0) {
printf("No file");
return 1;
}
int fin = open(argv[1], O_RDONLY);
if( !fin ) {
printf("open %s failed\n",argv[1]);
return 2;
}
int fout = open(argv[2], O_CREAT | O_WRONLY, 0624);
if( !fout ) {
printf("open %s failed\n",argv[2]);
close(fout);
return 2;
}
int rc = 0;
// process one line
rc = doline(fin,fout);
// or, process every line in file
for( ; rc = doline(fin,fout) >= 0; ) {
}
close(fin);
close(fh);
I'm currently learning and practicing c, but the exercise I'm doing wants each functions to have 25 lines limit (without changing { } or using single-line if statements!)
Please help if there's a way to make this even shorter.
void ft_write_file(void)
{
char c;
int fd;
int i;
i = 0;
if ((fd = open("write_exam", O_WRONLY | O_TRUNC | O_CREAT, 00777)) == -1)
{
ft_putstr("map error");
return ;
}
while (read(0, &c, 1))
{
write(fd, &c, 1);
if (c == '\n')
break ;
ft_allocate_g_var(i, c, 0);
i++;
}
int j = 0;
while (j < g_line)
{
while (read(0, &c, 1))
{
write(fd, &c, 1);
if (c == '\n')
break ;
}
j++;
}
close(fd);
}
To start with, don't try to do two things in one function. And try to write your functions with sensible arguments instead of hard-coding their subjects.
For example, your function is really doing two things:
Finding and potentially creating the output file (with a hard-coded name).
Copying the entire contents of one stream (hard-coded to stdin) to another stream.
So you could break that down: (prototypes only)
/* Returns fd or -1 on error */
int open_output(const char* name);
/* Returns number of bytes copied or -1 on error */
ssize_t copy_fd(int fd_dest, int fd_source);
Then your driver could be:
ssize_t copy_stdin_to_file(const char *name)
{
int fd = open_output(name);
if (fd < 0)
{
ft_putstr("Could not open output file");
return -1;
}
ssize_t copied = copy_fd(fd, 0);
if (copied < 0) {
ft_putstr("Could not write data.");
return copied;
}
}
A simple way would be to declare all the variables at the top in one line, for exemple :
char c; int fd; int i; i = 0;
Except from that I dont know, hope it can help a bit a least !
I am learner in C and I need to compile my code using shellforge and hence cannot use any library functions as they provide an error.
Can someone help me with the same.
This is what I have so far, I need help in comparing the 2 passwords and only then writing it to the file. Any help/modifications to my code to achieve this with an explanation will be highly appreciated.
#include <stdio.h>
int main()
{
int fd;
char username;
char kbinput[KBINPUT_SIZE];
char kbinputpassone[KBINPUTPASSONE_SIZE];
char kbinputpasstwo[KBINPUTPASSTWO_SIZE];
char passwordone;
char passwordtwo;
int count = 0;
int ret;
fd = open("test.txt", O_CREAT | O_RDWR,0666);
if(fd == -1)
{
printf("Error!");
exit(1);
}
write(1,"Enter the username",18);
do
{
read(0, &username, 1);
if (username == '\n')
break;
kbinput[count++] = username;
}
while (count < KBINPUT_SIZE - 1);
kbinput[count] = 0;
write(fd,username,10);
write(1,"Enter the password",18);
count =0;
do
{
read(0, &passwordone, 1);
if (passwordone == '\n')
break;
kbinputpassone[count++] = passwordone;
}
while (count < KBINPUTPASSONE_SIZE - 1);
kbinputpassone[count] = 0;
write(1,"Enter the password again",25);
count=0;
do
{
read(0, &passwordtwo, 1);
if (passwordtwo == '\n')
break;
kbinputpasstwo[count++] = passwordtwo;
}
while (count < KBINPUTPASSTWO_SIZE - 1);
kbinputpasstwo[count] = 0;
write(1,"The Passwords match",20);
write(fd, passwordone, 15);
return 0;
}
I have a problem at my C-lecture skill practice. My exercise is to read a text document (which is in the same directory like the program) char by char and write it reversed (so from the end to the beginning, char by char) at the Terminal (i have to work at Ubuntu).
Unfortunately it doesn't work - "read" only reads newline-chars (\n).
Can you find my mistake?
#include <sys/stat.h> //mode_t: accessing rights for the file
#include <fcntl.h> //for I/O
#include <unistd.h> //for file descriptors
#include <string.h> //for strlen
short const EXIT_FAILURE = 1;
short const EXIT_SUCCESS = 0;
char const* USAGE_CMD = "usage: write_file filename string_to_write\n";
char const* ERR_OPEN = "error in open\n";
char const* ERR_READ = "error in reading\n";
char const* ERR_CLOSE = "error in close\n";
char const* ERR_WRITE = "error in write\n";
int main(int argc, char** argv){
int fd = open(argv[1], O_RDONLY);
if(fd == -1){
write(STDERR_FILENO, ERR_OPEN, strlen(ERR_OPEN));
return EXIT_FAILURE;
}
int two_char_back = (-1)*sizeof(char); //shift-value for char
int one_back = -1; //shift-value for "no shift"
int length = lseek(fd, one_back, SEEK_END);//setting to one before oef
int i = 0; //for the loop
char buffer;
char* pbuffer = &buffer; //buffer for writing
while (i < length){
if (read(fd, pbuffer, sizeof(buffer)) == -1){ //READING
write(STDERR_FILENO, ERR_READ, strlen(ERR_READ));
return EXIT_FAILURE;
}
if(write(STDOUT_FILENO, pbuffer, sizeof(buffer)) == -1){ //WRITING
write(STDERR_FILENO, ERR_WRITE, strlen(ERR_WRITE));
return EXIT_FAILURE;
}
lseek(fd, two_char_back, SEEK_CUR); //STEPPING
i++;
}
if(close(fd) == -1){ //CLOSING
write(STDERR_FILENO, ERR_CLOSE, strlen(ERR_CLOSE));
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
This is wrong:
int two_char_back = (-1)*sizeof(char);
sizeof(char) is 1, you need -2
Haven't tried running it, but looks like two_char_back should be -2. The read advances the cursor, so -1 keeps reading the same one.
Also, just an option, you could make it more efficient by reading the whole file in then reversing it, then writing.
You have a typo in following line:
int two_char_back = (-1)*sizeof(char);
It must be:
int two_char_back = (-2)*sizeof(char);
As read() increments a cursor, you are actually reading the same character all the time e.g:
example text
^
|
After reading:
example text
^
|
After seeking:
example text
^
|
Thanks for your advices a lot!
& Thanks to my colleagues!
Now it works but I created kind of a new version, here it is:
#include <sys/stat.h> //mode_t: accessing rights for the file
#include <fcntl.h> //for I/O
#include <unistd.h> //for file descriptors
#include <string.h> //for strlen
short const EXIT_FAILURE = 1;
short const EXIT_SUCCESS = 0;
char const* USAGE_CMD = "usage: write_file filename string_to_write\n";
char const* ERR_OPEN = "error in open\n";
char const* ERR_READ = "error in reading\n";
char const* ERR_CLOSE = "error in close\n";
char const* ERR_WRITE = "error in write\n";
int main(int argc, char** argv){
int fd = open(argv[1], O_RDONLY); //OPENING
if(fd == -1){
write(STDERR_FILENO, ERR_OPEN, strlen(ERR_OPEN));
return EXIT_FAILURE;
}
int file_size = lseek(fd, 0, SEEK_END); //setting to eof
int i = file_size-1; //for the loop, runs from the end to the start
char buffer;
//the files runs from the end to the back
do{
i--;
lseek(fd, i, SEEK_SET); //STEPPING from the start
if (read(fd, &buffer, sizeof(buffer)) != sizeof(buffer)){ //READING
write(STDERR_FILENO, ERR_READ, strlen(ERR_READ));
return EXIT_FAILURE;
}
if(write(STDOUT_FILENO, &buffer, sizeof(buffer)) != sizeof(buffer)){ //WRITING
write(STDERR_FILENO, ERR_WRITE, strlen(ERR_WRITE));
return EXIT_FAILURE;
}
}while (i != 0);
buffer = '\n';
write(STDOUT_FILENO, &buffer, sizeof(buffer));//no error-det. due to fixed value
if(close(fd) == -1){ //CLOSING
write(STDERR_FILENO, ERR_CLOSE, strlen(ERR_CLOSE));
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}