Get output line by line from another function (another source file)? - c

I have two source files: counter.c and main.c:
counter.c:
#include <stdio.h>
int counter(void) {
for(int i = 0; i < 5; i++)
printf("%d\n", i);
return 0;
}
main.c:
#include <stdio.h>
int counter(void);
int main(void) {
char *line;
counter();
return 0;
}
What I want to do is to have each line that counter() prints to be assigned to the line variable so I can do printf("%s\n", line) myself in main.c.
(edit) Unfortunately, this example doesn't translate well to my actual code so maybe I'll just put it here:
https://github.com/venetwork/venet/blob/master/venet-show.c
What I need is to access the result of running this code on a line by line basis in a different source file (GTK3 GUI). The main function for my combined code will be in this file so main() in venet-show.c should be changed to, say, show(). As of this moment I just use an IO Channel (https://developer.gnome.org/glib/stable/glib-IO-Channels.html) to "stream" the output of venet-show.c to the GUI but I want to get ride of it. Any ideas?

So we pass an allocated memory address and not a pointer like you had to the function. This has storage for the result. Use the return snprintf to advance the pointer so not to overwrite previous results.
#include <stdio.h>
int counter(char *answer, size_t array_len) {
for(int i = 0; i < 5; i++)
{
size_t chars_printed = snprintf(answer, array_len, "%d\n", i);
answer+=chars_printed;
array_len-=chars_printed;
}
return 0;
}
int main(void) {
char line[10000];
counter(line, sizeof(line));
printf("%s", line);
return 0;
}

Related

Does WaitOnAddress return when values match or when values differ?

I am trying to use the WaitOnAddress() function to achieve read-write synchronization.
According to MSDN, WaitOnAddress() has the following declaration:
BOOL WaitOnAddress(
volatile VOID *Address,
PVOID CompareAddress,
SIZE_T AddressSize,
DWORD dwMilliseconds
);
and the following parameter definition:
CompareAddress
A pointer to the location of the previously observed value at Address. The function returns when the value at Address differs from the value at CompareAddress.
According to the definition, I should store and pass the current value of the watched address, so when the watch value changes, WaitOnAddress() will return. But this function does not work as I expected, so I wrote the following test code for WaitOnAddress() in Visual Studio (and also included linker library Synchronization.lib):
#include <stdio.h>
#include <stdlib.h> // atoi
#include <string.h>
// include these two files after including winsock2.h
#include <process.h>
#include <Windows.h>
#include <synchapi.h>
void* threads(void* num) {
int* number = (int*)num;
for (int i = 0; i < 10; i++) {
printf("number = %d\n", *number);
}
int catch = *number; // will be passed as CompareAddress
WaitOnAddress((int*)num, &catch, sizeof(int), INFINITE);
for (int i = 0; i < 10; i++) {
printf("number2 = %d, %d\n", catch, *(int*)num);
}
return NULL;
}
int main() {
int int_list[10];
for (int i = 0; i < 10; i++) {
int_list[i] = i;
_beginthread(threads, 0, (void*)&int_list[i]);
}
printf("hello\n");
Sleep(1000);
for (int i = 0; i < 10; i++) {
int_list[i] = 10 - i;
}
printf("changed\n");
Sleep(1000);
return 0;
}
In above code, WaitOnAddress() never returns even though the value it watches changes. But, if I change
int catch = *number;
to:
int catch = 10 - *number;
then WaitOnAddress() returns and the rest of the output is printed, as if it returns ONLY when the watched value matches the compared value.
But, I want to used the described behavior so my thread is released whenever the watched variable is changed.
According to the documentation:
Parameters
Address
The address on which to wait. If the value at Address differs from the
value at CompareAddress, the function returns immediately. If the
values are the same, the function does not return until another thread
in the same process signals that the value at Address has changed by
calling WakeByAddressSingle or WakeByAddressAll or the timeout
elapses, whichever comes first.
Although you modify the value of the original array in the second loop, the catch and num are always the same when calling WaitOnAddress in the thread, so the WaitOnAddress function will not return.
You can try to modify it to:
#include <stdio.h>
#include <stdlib.h> // atoi
#include <string.h>
// include these two files after including winsock2.h
#include <process.h>
#include <Windows.h>
void* threads(void* num) {
int* number = (int*)num;
printf("number = %d\n", *number);
int catch = *number; // will be passed as CompareAddress
WaitOnAddress((int*)num, &catch, sizeof(int), INFINITE);
printf("number2 = %d, %d\n", catch, *(int*)num);
return NULL;
}
int main() {
int int_list[10];
for (int i = 0; i < 10; i++) {
int_list[i] = i;
_beginthread(threads, 0, (void*)&int_list[i]);
}
printf("hello\n");
Sleep(1000);
printf("changed\n");
for (int i = 0; i < 10; i++) {
int_list[i] = 10 - i;
WakeByAddressSingle(&int_list[i]);
}
Sleep(1000);
return 0;
}
And it works for me:

C function returning different values while calling from main function

I have written a program which read values from a the file. The data in the file is in following format.
100 Full Name SomeDetails.
234 Full Name SomeDetails
Following is the program which i wrote.
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#define MAX 10
struct student
{
int rollno;
char name[20];
char course[25];
};
int main()
{
FILE *fptr;
fptr=fopen("records.txt","r");
struct student s[10];
int i=0,tstudent=0;
char che;
char line[100];
//SECTION : 1.1 -> READING NUMBER OF LINES
while(!feof(fptr))
{
che=fgetc(fptr);
if(che=='\n')
{
tstudent++;
}
}
printf("Total Lines in File = %d\n",tstudent);
fclose(fptr);
//SECTION : 1.2 -> READING RECORDS FROM FILE
fptr=fopen("records.txt","r");
char newString[20][20];
int ii,j,ctr;
j=0;
ctr=0;
for(i=0; i<tstudent; i++)
{
fgets(line,100,fptr);
printf("Value of Line %d = %s",i,line);
for(ii=0; ii<=(strlen(line)); ii++)
{
// if tab or NULL found, assign NULL into newString[ctr]
if(line[ii]=='\t'||line[ii]=='\0')
{
newString[ctr][j]='\0';
ctr++; //for next word
j=0; //for next word, init index to 0
}
else
{
newString[ctr][j]=line[ii];
j++;
}
}
}
for(ii=0; ii < ctr; ii++)
{
printf("\n%s",newString[ii]);
}
printf("Value of ctr = %d",ctr);
fclose(fptr);
}
Above code is working fine, BUT all the code is in main function, but i want to make a separate function which can be called from main file and return me every data of file in two dimensional or one dimensional array as return value.
Any help/suggestions would be appreciated.
I tried following CODE as a separate function.. NOT WORKING.
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
char readfile(int tstudent,FILE* filename)
{
//FUNCTION TO READ RECORDS FROM FILE.
FILE *fptr;
int i,k;
char line[100];
char newString[20][20];
int j=0,ctr=0;
fptr=fopen("records.txt","r");
for(i=0; i<tstudent; i++)
{
fgets(line,100,fptr);
printf("Value of Line %d = %s",i,line);
for(k=0; k<=(strlen(line)); k++)
{
// if tab or NULL found, assign NULL into newString[ctr]
if(line[k]=='\t'||line[k]=='\0')
{
newString[ctr][j]='\0';
ctr++; //for next word
j=0; //for next word, init index to 0
}
else
{
newString[ctr][j]=line[k];
j++;
}
}
}
return newString;
}
I defined a new variable char results[] in main function.. and tried to called the function as follows
results[]=readfile(tstudent,fptr)
but when trying to read results.. its showing garbage
char readfile(int tstudent,FILE* filename)
...
char newString[20][20];
...
return newString;
That can't be a good thing, right? You define readFile to return one single character (not a pointer, just one byte) and then return an array instead. We should not be surprised the compiler complained.
If you "fix" that be redefining the return type, you still have a problem because newString is an automatic local variable. The storage (memory) it defines is undefined outside the function.
The easiest way for a function to populate a structure (or array) in C is for the caller to pass it as a function parameter. So you wind up with something more like:
int readfile( FILE* input, char newString[][20], int tstudent )
where newString is defined the same way as you have it, but by the caller, not in readfile. Cf. the stdio functions like fgets; most of them require the caller to define the buffer they read into.
I'll just point out a few more mistakes.
Whenever you call a function -- especially an I/O function -- check for errors. You may want to read tstudent records, but how many are there? If you ask for 5 and find only 1, what then? Your read loop must test for end-of-file, and readfile must return the number of records read, else the caller will never know. Compare with how fread(3) works. Those Unix guys knew a thing or two about how to define a function!
Now your function looks something like this:
int readfile( FILE* input, char newString[][20], int tstudent ) {
char line[100], *s;
int i=0;
for( ; i < tstudent && (s = fgets(line, sizeof(line), input)) != NULL; i++ ) {
/* do stuff with line */
}
/* check for EOF/error if s is NULL, and report */
return i;
}

Why the code below excutes unexpected letters in the end of the string?

This is my code
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int countNumber(char string[],int number_[]);
int countNumber(char string[]);
int main(){
char string[] = "tran_huynh_minh_phuc";
int num = countNumber(string)+1;
int *number = (int *) calloc(num, sizeof(int));
countNumber(string,number);
for(int i=0;i<num;i++){
printf("%d\n",number[i]);
}
fflush(stdin);
char a[3][14];
strncpy(a[2], string+5, 5);
printf("%s",a[2]);
}
int countNumber(char string[],int *number)
{ int count=0;
int num_i=1;
number[0]=-1;
for(int i=0; i<strlen(string); i++)
{
if(string[i]=='_')
{ number[num_i] = i;
num_i++;
}
}
return count;
}
int countNumber(char string[])
{ int count=0;
for(int i=0; i<strlen(string); i++)
{
if(string[i]=='_')
{
count++;
}
}
return count;
}
this is my problem console results:
I am doing the program to get the substring which will get "tran","huynh","minh" from "tran_huynh_minh", however it is appearing some unexpected letters at the end of my substring. In addition, I tried many ways to fix it but it did not work. Can you find my mistakes?
Thanks
Minh Phuc
I think the intent for the bottom of the main block is something like this (this adds the null after the 'huynh' which was copied. By adding the null, when it goes to print a2, it knows when to stop. It looks like the desire was to put the second word in the array at index 2 (presumably being done in a loop once it was working or the like):
strncpy(a[2], string + 5, 5);
a[2][5] = '\0';
printf("%s", a[2]);
If you run something equivalent to this, you should see the expected output. However, you likely also see a warning on the strncpy function and considering using strncpy_s (depending what you are using to compile. It looks like you are on windows). If you replace the function call with strncpy_s (assuming Visual Studio), you will get the desired result without adding the null at the end separately. Note it expects a size of the destination array as a safeguard (14 in this case).
See this link as well as this one.

when compiling I get this error, I do not know what is wrong

I'm passing a matrix to a text file
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int llenarMatriz() {
int matriz[3][3]={1,2,3,4,5,6,7,8,9};
return matriz[3][3];
}
void guardarMatriz(int matriz[3][3]) {
char direccion[]="C:\\Users\\Usuario\\Desktop\\DIBU.txt";
FILE *archivo = fopen(direccion, "w");
if (archivo == NULL) {
exit(EXIT_FAILURE);
}
char linea[20];
sprintf(linea, "%d %d\n", 3, 3);
fputs(linea, archivo);
for (int i = 0; i < 3; i++) {
linea[0] = '\0';
for (int j = 0; j < 3; j++){
char buffer[10];
sprintf(buffer, "%d ", matriz[3][3]);
strcat(linea, buffer);
}
int len = strlen(linea);
linea[len - 1] = '\n';
fputs(linea,archivo);
}
fclose(archivo);
}
int main() {
llenarMatriz();
guardarMatriz(int matriz[3][3]);
system("pause");
return 0;
}
Error message;
In function 'main':
error: expected expression before 'int'
guardarMatriz(int matriz[3][3]);
You have two problems in your code. First you don't initialize a 2-D array correctly. It should look like this:
int matriz[3][3]={{1,2,3},{4,5,6},{7,8,9}};
second, you don't pass a type name to the function call to declare your variable, so it should look like this:
int matriz[3][3];
llenarMatriz();
guardarMatriz(matriz);
guardarMatriz(int matriz[3][3]);
Don't include the type and the dimensions when passing parameters to a function.
Also, when you call a function returning something, you should use the correct type (an int is not able to return a 2D array of int), and you must store the return somewhere.
In this case you can return a compound literal:
void *llenarMatriz(void)
{
return (int [][3]){{1,2,3},{4,5,6},{7,8,9}};
}
and in main:
int main(void) /* void is the correct argument for `main` */
{
int (*matriz)[3] = llenarMatriz(); /* A pointer to an array of int 3 */
guardarMatriz(matriz);
system("pause");
return 0;
}
If you don't want to declare the array inside main you can use the result of the first function as the argument of the second one:
guardarMatriz(llenarMatriz());
or you can pass the compound literal directly:
guardarMatriz((int [][3]){{1,2,3},{4,5,6},{7,8,9}});

Whats wrong with this basic shell program? it will run fine for the first few commands but results always ends in a seg fault

I have to build a simple shell program using lex and c code. The lex portion is for breaking down the input. It has been provided for me and I'm not expected to change it. I'm in the process of getting my code to run basic commands like "ls". It seems to work the first few times I run the command but eventually always seg faults. Here is the lex code provided:
%{
int _numargs = 10;
char *_args[10];
int _argcount = 0;
%}
WORD [a-zA-Z0-9\/\.-]+
SPECIAL [()><|&;*]
%%
_argcount=0;
_args[0]=NULL;
{WORD}|{SPECIAL} {
if(_argcount < _numargs-1) {
_args[_argcount++]= (char *)strdup(yytext);
_args[_argcount]= NULL;
}
}
\n return (int)_args;
[ \t]+
.
%%
char **getln() {
return (char **)yylex();
}
This is the C code:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/wait.h>
extern char **getln();
int main() {
int i;
char **args;
int child1;
int status1;
int counter=0;
int argCount = 1;
char **array = (char **)malloc(1500 * sizeof(char *));
for (i = 0; i < 1500; ++i) {
array[i] = (char *)malloc(500);
}
strcpy(array[0],"ls\0");
array[1] = NULL;
while(1) {
args = getln();
printf("is error here?");
strcpy(array[0], args[counter]);
for(i = (counter+1); args[i] != NULL; i++) {
printf("\nRight before copying to subarray");
strcpy(array[argCount], args[i]);
argCount++;
}
array[argCount] = NULL;
if (strcmp(args[counter],"exit")==0) exit(0);
child1 = fork();
if(child1==0){
execvp(array[0], array);
printf("Unknown command, please try again.");
exit(1);
}
else{
while (wait(&status1) != child1);
}
for(i = 0; args[i] != NULL; i++) {
printf("Argument %d: %s\n argCount: %d", i, args[i], argCount);
}
argCount = 1;
counter++;
}
}
Thanks in advance for any advice. If there is some simple way to adjust the getln() function to overwrite the args array each time it is called that might be easier than what I am attempting but I have no idea how to go about that.
It seems like you have put
_argcount=0;
_args[0]=NULL;
at the top of the rules section in hopes that these statements would be executed at the beginning of yylex(). And you've noticed that they aren't executed (it keeps appending to the previous values because _argcount never goes back to 0).
The obvious thing to do is move those statements into getln() just before the yylex().
What you have now is a lexer that will ignore the string _argcount=0; in the input because it will match that pattern and there's no action to go with it. The second line is even cooler since the [0] is a character class. It makes the lexer ignore the string _args0=NULL;

Resources