Why isn't my write method initialised? - c

I have been trying to write words that are given by the user in the command shell,but for some reason my program instantly quits after the read() function,so the text in main() :"in main2\n" is never even written. I have been trying to locate my problem for about an hour now and can't seem to find it.
# include <stdio.h>
void write_zin(const char* zin,int length_zin){
const char * runner =zin;
printf("out of loop\n");
while(runner!=(runner+length_zin)){
printf("%c",*runner);
runner++;
}
}
void read(char* zin,int NUMBER_LETTERS,int NUMBER_WORDS){
int i ;
char woord[NUMBER_LETTERS+1];
zin[0]='\0';
for(i =0;i<NUMBER_WORDS;i++){
printf("Give a word with %i letters\n",NUMBER_LETTERS);
scanf("%s",woord);
strcat(zin,woord);
strcat(zin,'\0');
}
strcat(zin,'\0');
}
int main(){
const int NUMBER_LETTERS = 5;
const int NUMBER_WORDS = 2;
char zin[(NUMBER_LETTERS+1)*NUMBER_WORDS];
printf("in main 1\n");
read(zin,NUMBER_LETTERS,NUMBER_WORDS);
printf("in main 2\n");
write_zin(zin,(NUMBER_LETTERS+1)*NUMBER_WORDS);
printf("in main3\n");
return 0;
}

There are a couple errors in your code:
Function void read(char* zin,int NUMBER_LETTERS,int NUMBER_WORDS)
If you concatenate words separated by '\0' you will end having just one string, because every string function will stop at the first '\0' and will not process further characters. So you cannot use strcat(zin,'\0');
If you want to mark the separation between strings use another special character as '\n' The final function will be:
void read(char* zin,int NUMBER_LETTERS,int NUMBER_WORDS){
int i ;
char woord[NUMBER_LETTERS+1];
for(i =0;i<NUMBER_WORDS;i++){
printf("Give a word with %i letters\n",NUMBER_LETTERS);
scanf("%s",woord);
strcat(zin,woord);
}
}
2. Function void write_zin(const char* zin,int length_zin)
You cannot ever change the condition of a loop inside a loop. That is what you are doing, because runner is always changing inside the loop, and in addition it is part of your condition.
while(runner!=(runner+length_zin)){
printf("%c",*runner);
runner++;
}
The final function is:
void write_zin(const char* zin,int length_zin){
const char * runner =zin;
printf("out of loop");
while(*runner){
printf("'%c'",*runner);
runner++;
}
}

Related

problems utilitizing small pauses in c code using nanosleep

I am a C beginner and trying this and that.
I want to display a string letter by letter with tiny pauses in between. So my idea was a small pause using sleep or usleep after displaying each char but I read that using nanosleep in your own function makes more sense. So I put my little pauses in a function "msleep" to get microseconds pauses.
I output my string 3 times.
Once in the main(), then in a do-while-loop in a function (fancyOutput) char by char, and eventually in the same function with printf again to check, if it was handled over correctly.
My problem: I expected, that the middle output would work char by char and separated by 100/1000 seconds breaks, but what I experience is a long break before chowing any char and then a fast output if line two and three. It looks like the compiler "realized what I am planning to do and wants to modify the code to be more efficient." So all my pauses seemed to be combined in one long break.
Maybe you remeber the captions in the tv series "x files" - something like that I want to produce.
For sure there are better and more sophisticated ways to archieve what I am going to try but I want to learn and understand what is going on. Can someone help me with that?
I am using codeclocks on a debian-based distro with gcc.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int msleep(long tms);
void fancyOutput(char inputToOutput[]);
int msleep(long tms)
{
struct timespec ts;
int ret;
if (tms < 0)
{
return -1;
}
ts.tv_sec = tms / 1000;
ts.tv_nsec = (tms % 1000) * 1000000;
do
{
// printf("sleeping for %d", ret);
ret = nanosleep(&ts, &ts);
}
while (ret);
return ret;
}
void fancyOutput(char inputToOutput[])
{
int counter = 0;
do
{
printf("%c", inputToOutput[counter]);
msleep(100);
++counter;
}
while (!(inputToOutput[counter]=='\0'));
printf("\n");
printf("%s\n", inputToOutput); // only check, if string was properly handled over to function
}
char output[] = "This string shall appear char by char in the console.";
void main(void)
{
printf("%s\n", output); // only check, if string was properly set and initialized
fancyOutput(output); // here the function above is called to output the string char by cchar with tiny pauses between
}
You are getting problem with buffer.
When you use printf with no \n (new line) C is buffering the display in order to display information block by block (to optimize displaying speed).
Then you need to either add a \n to your printf or add a flush of the stdout.
An other solution will be to use stderr, which got no buffer, but stderr is meant for error not output :)
You can also check setvbuf in order to change the buffering.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int msleep(long tms);
void fancyOutput(char inputToOutput[]);
int msleep(long tms)
{
struct timespec ts;
int ret;
if (tms < 0)
{
return -1;
}
ts.tv_sec = tms / 1000;
ts.tv_nsec = (tms % 1000) * 1000000;
do
{
// printf("sleeping for %d", ret);
ret = nanosleep(&ts, &ts);
}
while (ret);
return ret;
}
void fancyOutput(char inputToOutput[])
{
int counter = 0;
do
{
printf("%c", inputToOutput[counter]);
flush(stdout);
msleep(100);
++counter;
}
while (!(inputToOutput[counter]=='\0'));
printf("\n");
printf("%s\n", inputToOutput); // only check, if string was properly handled over to function
}
char output[] = "This string shall appear char by char in the console.";
void main(void)
{
printf("%s\n", output); // only check, if string was properly set and initialized
fancyOutput(output); // here the function above is called to output the string char by cchar with tiny pauses between
}
So, I tried the solution to place fflush(stdout); directly after the char-output in the loop. It worked as intended.
Summarizing for those with similar problems (guess this also happens with usleep and similar self-made functions):
As I understaood, printf "collects" data in stdout until it "sees" \n, which indicates the end of a line. Then printf "releases" stdout. So in my initial post it "kept" each single char in stdout, made a pause after each char and finally released stdout in one fast output.
So fflush(stdout); after each char output via empties stdout char by char.
Hope it can help others.

Suppress printing a new prompt when pressing tab with Readline

When using the auto completion with the Readline library in C, the prompt is reprinted when typing the tab key twice:
(prompt) view NAME_OF_F (user presses tab twice)
NAME_OF_FILE1 NAME_OF_FILE2 (suggestions by Readline)
(prompt) view NAME_OF_F
I'd like to suppress the reprinting of the prompt on the 3rd line by keeping the first line printed with the suggestions below it like such:
(prompt) view NAME_OF_F (user presses tab twice)
NAME_OF_FILE1 NAME_OF_FILE2 (suggestions by Readline)
I'd like the cursor back at the end of the first line that has the prompt.
Compiled with gcc -Wall -O0 -ggdb -fno-builtin rline.c -o rline -lreadline -ltermcap.
Here's a code sample:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <readline/readline.h>
int execute_line(char *line);
void initialize_readline();
static char **fileman_completion(char *text, int start, int end);
static char *command_generator(char *text, int state);
char *command[] = { "view", "quit", (char *)NULL };
int done; /* When non-zero, this global means the user is done using this program. */
int main(int argc, char **argv)
{
char *line;
initialize_readline(); /* Bind our completer. */
for ( ; done == 0; ) {
line = readline("> ");
if (!line)
break;
if (*line)
execute_line(line);
free(line);
}
return 0;
}
/* String to pass to system(). This is for the VIEW command. */
static char syscom[1024];
int execute_line(char *line)
{
int i = 0;
char *word;
/* Isolate the command word. */
while (line[i] && whitespace(line[i]))
i++;
word = line + i;
while (line[i] && !whitespace(line[i])) i++;
if (line[i]) line[i++] = '\0';
if (strcmp(word, "quit") == 0) {
done = 1;
return 0;
} else if (strcmp(word, "view")) {
fprintf(stderr, "%s: Choose only \"view FILE\" or \"quit\" as your command.\n", word);
return -1;
}
/* Get argument to command, if any. */
while (whitespace(line[i])) i++;
word = line + i;
if(!word || !*word) {
fprintf(stderr, "view: Argument required.\n");
return -1;
}
sprintf(syscom, "more %s", word);
return system(syscom);
}
void initialize_readline()
{
rl_readline_name = "rline";
rl_attempted_completion_function = (rl_completion_func_t *)fileman_completion;
}
static char **fileman_completion(char *text, int start, int end)
{
if (start == 0)
return rl_completion_matches(text, (rl_compentry_func_t *)*command_generator);
return NULL;
}
static char *command_generator(char *text, int state)
{
static int list_index, len;
char *name;
if (!state) {
list_index = 0;
len = strlen(text);
}
while ((name = command[list_index++]))
if (strncmp(name, text, len) == 0)
return strdup(name);
return NULL;
}
The program only accepts the commands view FILE_NAME to view the contents of a file and quit to exit the program.
The example is a shortened version of a sample program found here.
I don't think that readline has anything like that built in, but it does provide a lot of customisation possibilities if you want to try to write the logic yourself.
You could try writing a custom rl_completion_display_matches_hook to display the completion list. But it's not entirely clear to me how you would restore the cursor position afterwards. I don't think readline has a public interface for either finding or resetting the cursor position. (And, of course, it's possible that the completion list was so big that the original command scrolled off the screen.)
As an alternative, I was able use the hook to print the completion list over top of the current line and then redisplay the prompt after the completion list (although I cheated by assuming that the current input is always just one line). That's not quite what you asked for, but it may be useful for demonstration purposes. I used the following custom match printer:
static void display_matches(char** matches, int len, int max) {
putp(carriage_return);
putp(clr_eol);
putp(cursor_up);
rl_display_match_list(matches, len, max);
rl_forced_update_display();
}
I also added the following to the initialisation function:
rl_completion_display_matches_hook = display_matches;
setupterm(NULL, 1, (int*)0);
Thanks #rici for the inspiration. I got it working with his function with some modifications.
In order for this to work properly you need to download the readline library. In the rlprivate.h file from readline, I removed the lines char **lines;, and the line #include "realdine.h" from display.c. Then in your own .c you must have an #include </PATH/TO/display.c>. In that display.c, an #include points to the modified rlprivate.h. All of this so that I can have access to _rl_move_vert(1).
static void display_matches(char** matches, int len, int max)
{
int saved_point = rl_point;
char *saved_line = rl_copy_text(0, rl_end);
rl_save_prompt();
rl_replace_line("", 0); // Clear the previous text
putp(cursor_up);
_rl_move_vert(1);
rl_display_match_list(matches, len, max);
putp(cursor_up);
rl_restore_prompt();
rl_replace_line(saved_line, 0);
rl_point = saved_point;
rl_redisplay();
putp(cursor_down);
free(saved_line);
}

fscanf != eof Clang compiler, anomalous behaviour

I'm having an aggravating issue that I can't understand,
void file_count(FILE* stream,int* const num)
{
int temp;
while((fscanf(stream,"%d",&temp))!=EOF)
{
(*num)++;
}
}
With this piece of program, I read from a file taking all the numbers inside it, and very time I take a number a counter increases so I can count how many elements are in the file.
In this file there are 6 numbers, but if I run this code the counter skyrockets to 32777...
If I compile it with gcc, there's no problem and the counter is 6 as expected. Is this a bug of clang? Is it a feature that I'm not aware of?
The file contains:
22 30 30 21 25 29
The whole code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char* string;
typedef struct student
{
int flag;
char name[25];
char surname[25];
char dorm[25];
int* grades;
}
Student;
void check_input(const int argc,const string* const argv);
void check_file(FILE* stream);
void file_count(FILE* stream,int* const num);
void update_student(const string* const infos,Student* const student,const int grades,FILE* stream);
void print_student(FILE* stream,Student const student,const int grades);
int main(int argc, string argv[])
{
check_input(argc,argv);
FILE* one,* two;
string info[]={"David","Malan","Mather"};
Student student;
int grades;
one=fopen(argv[1],"r");
check_file(one);
file_count(one,&grades);
update_student(info,&student,grades,one);
fclose(one);
two=fopen(argv[2],"w");
check_file(two);
print_student(two,student,grades);
fclose(two);
free(student.grades);
system("cat out");
return 0;
}
void check_input(const int argc,const string* const argv)
{
if(argc!=3)
{
printf("\x1B[31mError: %s takes two arguments!\x1B[0m\n",argv[0]);
exit(EXIT_FAILURE);
}
}
void check_file(FILE* stream)
{
if(stream==NULL)
{
printf("\x1B[31mError:invalid file.\x1B[0m\n");
exit(EXIT_FAILURE);
}
}
void file_count(FILE* stream,int* const num)
{
int temp;
printf("reading file...\n");
while((fscanf(stream,"%i",&temp))!=EOF)
{
(*num)++;
}
printf("\x1B[33mthe value read were %i\x1B[0m\n",*num);
}
void update_student(const string* const infos,Student* const student,const int grades,FILE* stream)
{
rewind(stream);
student->grades=malloc(grades*sizeof(int));
strcpy(student->name,infos[0]);
strcpy(student->surname,infos[1]);
strcpy(student->dorm,infos[2]);
student->flag=0;
for(int i=0;i<grades;i++)
{
fscanf(stream,"%i",&student->grades[i]);
}
}
void print_student(FILE* stream,Student const student,const int grades)
{
printf("Writing to file..\n");
fprintf(stream,"%i %s %s %s ",student.flag,student.name,student.surname,student.dorm);
for(int i=0;i<grades;i++)
{
fprintf(stream,"%i ",student.grades[i]);
}
printf("\x1B[32mFile successfully written..\x1B[0m\n");
}
Your code is dangerous, because an incorrect file sends it into an infinite loop.
Once fscanf with %d finds an input that cannot be interpreted as an int, the function returns zero without making any progress on consuming the input. Therefore, the loop never reaches EOF.
You can fix this issue by looping only as long as the input is consumed:
while(fscanf(stream,"%d",&temp) == 1) {
...
}
Now you need a way to communicate to the caller if the count is correct or not. You can do that by returning one if EOF is reached, and zero otherwise:
int file_count(FILE* stream,int* const num) {
int temp, last;
while((last = fscanf(stream,"%d",&temp)) == 1) {
(*num)++;
}
return last == EOF;
}
I tried with fscaf==1 it still reaches 32777
This happens because you are not initializing grades in the caller. You should define it as int grades = 0, or add *num = 0 before entering the loop in file_count.
The current ISO C standard defines the return value of fscanf() as
The fscanf function returns the value of the macro EOF if an input failure occurs before the first conversion (if any) has completed. Otherwise, the function returns the number of input items assigned, which can be fewer than provided for, or even zero, in the event of an early matching failure.
Verbatim quote from the ISO-C Standard (no public link available, the standard is not public AFAIK)
If there is data to read, but that data cannot be successfully matched, this function will return 0. It will only return EOF (which is typically -1) if there is no data to read because the stream you are reading from is in EOF state or had another read error.
So if you had a file like that:
23 a 57
The loop will never terminate. On first scan it will read 23 and return 1 (one value matched). On next call it will return 0, as a cannot be matched to an integer. Yet, it also won't move the file pointer beyond a. So on next call, it tries to match a again and it will fail again. This continues endlessly.

counting number of lines not working correctly through loop

I'm trying to count the number of lines of a wchar_t string on my C program using 2 methods: 1st method using a loop through the buffer counting "\n", the 2nd one is using wcstok() however I got only the 2nd method returning the correct lines number, the 1st one returns always 0: here is my full program code:
#include <stdio.h>
#include <string.h>
const wchar_t* ret2line_template = L"\n";
int get_lines_count1(wchar_t* w){
int count=0;
int i;
for(i=0;i<wcslen(w);i++)if((w[i]==ret2line_template[0]) && (w[i+1]==ret2line_template[1]))count++;
return count;
}
int get_lines_count2(wchar_t* w){
int count=0;
wcstok(w, ret2line_template);
do{count++;}while(wcstok(0, ret2line_template));
return count;
}
int main(){
const wchar_t* s = L"00\n11\n22\n33";
const wchar_t* w;
w = calloc(sizeof(wchar_t*), wcslen(s)+1);
wcscpy(w, s);
printf("lines count from get_lines_count1 = %d\n", get_lines_count1(w)); //this returns 0: incorrect value
printf("lines count from get_lines_count2 = %d\n", get_lines_count2(w)); //this returns 4: the correct value
getch();
}
so what's wrong with my get_lines_count1 function and its loop? how to fix that problem? please help.
You're only incrementing count in the first function if you match on a newline followed by a null char.
This:
ret2line_template[1]
in your conditional expression is looking at the second wchar_t in this:
const wchar_t* ret2line_template = L"\n";
which is the zero terminator. None of the pairs of wchar_t's in your string match this, so the result is zero. Just look for a L'\n'. If there are chars left after the last one, add one more "line" to your count (the last one that has no L'\n' trailing.

User entered string run a particular function in c

Guys so I'm working on the web service assignment and I have the server dishing out random stuff and reading the uri but now i want to have the server run a different function depending on what it reads in the uri. I understand that we can do this with function pointers but i'm not exactly sure how to read char* and assign it to a function pointer and have it invoke that function.
Example of what I'm trying to do: http://pastebin.com/FadCVH0h
I could use a switch statement i believe but wondering if there's a better way.
For such a thing, you will need a table that maps char * strings to function pointers. The program segfaults when you assign a function pointer to string because technically, a function pointer is not a string.
Note: the following program is for demonstration purpose only. No bounds checking is involved, and it contains hard-coded values and magic numbers
Now:
void print1()
{
printf("here");
}
void print2()
{
printf("Hello world");
}
struct Table {
char ptr[100];
void (*funcptr)(void)
}table[100] = {
{"here", print1},
{"hw", helloWorld}
};
int main(int argc, char *argv[])
{
int i = 0;
for(i = 0; i < 2; i++){
if(!strcmp(argv[1],table[i].ptr) { table[i].funcptr(); return 0;}
}
return 0;
}
I'm gonna give you a quite simple example, that I think, is useful to understand how good can be functions pointers in C. (If for example you would like to make a shell)
For example if you had a struct like this:
typedef struct s_function_pointer
{
char* cmp_string;
int (*function)(char* line);
} t_function_pointer;
Then, you could set up a t_function_pointer array which you'll browse:
int ls_function(char* line)
{
// do whatever you want with your ls function to parse line
return 0;
}
int echo_function(char* line)
{
// do whatever you want with your echo function to parse line
return 0;
}
void treat_input(t_function_pointer* functions, char* line)
{
int counter;
int builtin_size;
builtin_size = 0;
counter = 0;
while (functions[counter].cmp_string != NULL)
{
builtin_size = strlen(functions[counter].cmp_string);
if (strncmp(functions[counter].cmp_string, line, builtin_size) == 0)
{
if (functions[counter].function(line + builtin_size) < 0)
printf("An error has occured\n");
}
counter = counter + 1;
}
}
int main(void)
{
t_function_pointer functions[] = {{"ls", &ls_function},
{"echo", &echo_function},
{NULL, NULL}};
// Of course i'm not gonna do the input treatment part, but just guess it was here, and you'd call treat_input with each line you receive.
treat_input(functions, "ls -laR");
treat_input(functions, "echo helloworld");
return 0;
}
Hope this helps !

Resources