I've looked around but can't seem to find how to do this. I want the value of empty lines from test2(int *f) to be passed to test1() and be printed on the screen.
Variant 1 of code:
#include <stdio.h>
#include <string.h>
void test1();
void test2(int *f);
void test1(){
int a;
test2(&a);
printf("%d \n", a);
}
void test2(int *f){
char str[80];
int lines, i, emptylines=0;
*f=emptylines;
printf("Type a program here. Ctrl+Z and enter to stop.\n");
fflush(stdin);
while(gets(str)!=NULL && strcmp(str, "qq")) {
for(i=0; i<strlen(str); i++){
if(str[i]!='\n') lines=1;
}
if(!lines) emptylines++;
lines=0;
}
}
int main() {
test1();
return 0;
}
Variant 2 of code:
#include <stdio.h>
#include <string.h>
void test1();
void test2(int *f);
void test1(){
int a;
test2(&a);
printf("%d \n", a);
}
void test2(int *f){
char str[80], *p;
int lines, emptylines=0;
*f=emptylines;
printf("Type a program here. Ctrl+Z and enter to stop.\n");
fflush(stdin);
while(gets(str)!=NULL && strcmp(str, "qq")) {
p=str;
lines=0;
while(*p!='\0') {
if(*p!=' ') {
lines=1;
}
p++;
}
if(lines==0){
emptylines++;
lines=0;
}
}
}
int main() {
test1();
return 0;
}
You are putting *f=emptylines in the beginning of the function void test2(int *f); Then you calculate emptylines but this will not affect the value pointed-to by f.
You need to move that assignment *f=emptylines to the end of the function, just before returning and after having calculated emptylines
void test2(int *f){
// stuff to calculate emptylines
....
*f=emptylines; // at the end
}
When you write
*f = emptylines;
you are copying the value of emptylines into the space pointed to by f. Then when you update emptylines later, the value pointed to by f doesn't change because you made a copy.
Rather than using another variable emptylines just use the parameter f directly to compute the value. Though I'd give it a more descriptive value than f, something like numEmptyLines.
#include <stdio.h>
#include <string.h>
void test1();
void test2(int *numEmptyLines);
void test1(){
int a;
test2(&a);
printf("%d \n", a);
}
void test2(int *numEmptyLines){
char str[80];
int lines, i;
*numEmptyLines = 0;
printf("Type a program here. Ctrl+Z and enter to stop.\n");
fflush(stdin);
while(gets(str)!=NULL && strcmp(str, "qq")) {
for(i=0; i<strlen(str); i++){
if(str[i]!='\n') lines=1;
}
if(!lines) (*numEmptyLines)++;
lines=0;
}
}
int main() {
test1();
return 0;
}
Related
I'm trying to initialize array *dip inside "leggif1", inside it if you do a print it's all normal but if you try to print in the main, after the initialization, everything loses its values.
Same thing happen with ADT of first grade "Divisione" and i can't understand why (even though they are passed "by reference" thanks to their pointers).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
int matricola;
char nome[20+1],cognome[20+1];
int comp[4];
}dipendente;
typedef struct divisione *Divisione;
struct divisione{
dipendente *dip;
char nome[10+1];
int terna[4][3]; //numero minimo di addetti,competenza minima totale, competenza ottimale totale
//per ognuna delle 4 tipologie
};
void leggif1(dipendente *dip, char *filename);
int leggif2(Divisione *Div, char *filename);
void DIVstampa(Divisione *Div,char *filename,int D);
Divisione DIVinit();
void DIVfree(Divisione *Div);
int main(int argc,char **argv) {
dipendente *dip;
Divisione *Div;
leggif1(dip,argv[1]);
int D=leggif2(Div, argv[2]);
DIVstampa(Div,"stdout",D);
return 0;
}
void leggif1(dipendente *dip, char *filename) {
FILE *fp=fopen(filename,"r");
int i,N;
fscanf(fp,"%d",&N);
dip=malloc(N*sizeof(dipendente));
for(i=0;i<N;i++)
fscanf(fp,"%d %s %s %d %d %d %d",&dip[i].matricola,dip[i].nome,dip[i].cognome,
&dip[i].comp[0],&dip[i].comp[1],&dip[i].comp[2],&dip[i].comp[3]);
}
int leggif2(Divisione *Div, char *filename) {
FILE *fp=fopen(filename,"r");
int i,j,D;
fscanf(fp,"%d",&D);
Div=malloc(D*sizeof(Divisione));
for(i=0;i<D;i++)
Div[i]=DIVinit();
for(i=0;i<D;i++) {
fscanf(fp, "%s", Div[i]->nome);
for (j = 0; j < 4; j++)
fscanf(fp, "%d %d %d", &Div[i]->terna[j][0], &Div[i]->terna[j][1], &Div[i]->terna[j][2]);
}
return D;
}
void DIVstampa(Divisione *Div, char *filename, int D) {
FILE *fp;
if(strcmp(filename,"stdout")==0)
fp=stdout;
else
fp=fopen(filename,"w");
int i,j;
for(i=0;i<D;i++) {
fprintf(fp,"%s\n", Div[i]->nome);
for(j=0;j<4;j++)
fprintf(fp,"%d %d %d\n", Div[i]->terna[j][0], Div[i]->terna[j][1], Div[i]->terna[j][2]);
}
}
Divisione DIVinit(){
Divisione Div=malloc(sizeof (*Div));
return Div;
}
void DIVfree(Divisione *Div){
free(Div);
}
The leggif1 function ignores the value of dip and assigns it a new value. That value is never returned to main.
The type of dip is dipendente* and when called in main the value of the pointer is passed to the function. Overwriting that local copy in the function does not affect the value of the pointer in main.
C only has 'call by value', always make sure you known what that value represents.
This can be solved by returning the dip from the function instead of taking it as a parameter:
dipendente* leggif1(char *filename)
{
//open file and read N
dipendente *dip = malloc(N * sizeof *dip);
if (!dip) {
return NULL;
}
// read in the data
return dip;
}
another way is to use a dipendente** (a pointer to a pointer) but that would, in this case, make the code needlessly complex.
The leggif2 function has the same problem.
I created the following code, it compiles but it doesen't run properly. It shows some imput witch is correct, but after that, instead of printing according to the line printf(prod[0].dr[0]); it enters an "not responding" state. If you instead write printf(prod[0].dr); it works perfectly. I need to be able to print each character individualy (so I need something like printf(prod[0].dr[0]); that works)
If the question is to broad, please comment and I will try to specify every detail.
Thanks!
#include <stdio.h>
FILE *f, *g;
struct productie
{
char st, dr[20];
int realizabil;
}prod[30];
int citire(FILE *f){
char sir[100];
int i=0,j;
while(!feof(f))
{
fgets(sir,100,f);
prod[i].st=sir[0];
for(j=3;j<strlen(sir);j++)
prod[i].dr[j-3]=sir[j];
i++;
}
return i;
}
int exista(char sir[],char c)
{
int i;
for(i=0;i<strlen(sir);i++)
{
if(c==sir[i])
return 1;
}
return 0;
}
void neterminale(struct productie p[],int n, char N[])
{
int k=0;
int i,j;
for(i=0;i<n;i++)
{
if(isupper(p[i].st) && !exista(N,p[i].st))
N[k++]=p[i].st;
for(j=0;j<strlen(p[i].dr);j++)
if(isupper(p[i].dr[j]) && !exista(N,p[i].dr[j]))
N[k++]=p[i].dr[j];
}
N[k]='\0';
}
void terminale(struct productie p[],int n, char T[],char N[])
{
int k=0;
int i,j;
for(i=0;i<n;i++)
{
if(!exista(N,p[i].st) && !exista(T,p[i].st)&& p[i].st!='$')
T[k++]=p[i].st;
for(j=0;j<strlen(p[i].dr);j++)
if(!exista(N,p[i].dr[j]) && !exista(T,p[i].dr[j]) && p[i].dr[j]!='$')
T[k++] = p[i].dr[j];
}
T[k]='\0';
}
void afisare(FILE *g,int n){
int i;
for(i=0;i<n;i++)
fprintf(g,"%c -> %s",prod[i].st, prod[i].dr);
}
int main(){
char N[30];
char T[30];
int i,j,n;
f=fopen("in.txt","r");
n=citire(f);
neterminale(prod,n,N);
printf("\nNeterminalele sunt:{");
for(i=0;i<strlen(N);i++)
printf("%c ",N[i]);
printf("}");
terminale(prod,n,T,N);
printf("\nTerminalele sunt:{");
for(i=0;i<strlen(T);i++)
{
printf(" %c ",T[i]);
}
printf("}");
printf(prod[0].dr[0]); //AT THIS LINE IS THE PROBLEM
g=fopen("out.txt","w");
afisare(g,n);
fclose(f);
fclose(g);
return 0;
}
The in.txt :
S->aS
S->a
S->$
S->AB
A->b
B->c
If you want to print a string directly, you need to provide a pointer to the first character, not the first character itself:
printf(&(prod[0].dr[0]));
or
printf(prod[0].dr);
But you can't limit this to a single char (there is no nprintf function).
the code is:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 20
typedef struct word{
char word[20];
int occurrance;
} word;
int array_word_creator(word *array, FILE *fp);
void initialize(word array[], int max);
void comparator(word array[], int max, FILE *fp);
void printer(word array[], int max);
int main(int argc, char *argv[])
{
FILE *f_sent, *f_words;
word *array;
int arr_lenght=0;
if(argc!=3)
{
printf("Wrong argument number, please use NAME FILE1 FILE2;\n");
exit(EXIT_FAILURE);
}
if((f_sent=fopen(argv[1], "r"))==NULL||(f_words=fopen(argv[1], "r"))==NULL)
{
printf("Can't find or open the files, please check if the name is correct\n");
exit(EXIT_FAILURE);
}
arr_lenght=array_word_creator(array, f_words);
comparator(array, arr_lenght ,f_sent);
printer(array, arr_lenght);
return 0;
}
int array_word_creator(word *array, FILE *fp)
{
int n,i=0;
fscanf(fp,"%d",&n);
*array= malloc(n*sizeof(word));
while(fscanf(fp,"%s", array[i].word)!=EOF)
{
i++;
}
initialize(array,n);
return n;
}
void initialize(word array[], int max)
{
int i;
for(i=0;i<max;i++)
{
array[i].occurrance=0;
}
}
void comparator(word array[], int max, FILE *fp)
{
char word[MAX];
int i;
while(fscanf(fp,"%s", word)!=EOF)
{
for(i=0;i<max;i++)
{
if(strcmp(word, array[i].word)==0)
{
array[i].occurrance++;
}
}
}
}
void printer(word array[], int max)
{
int i;
for(i=0;i<max;i++)
{
if(array[i].occurrance>0)
{
printf("The word '%s' occurs %d times\n", array[i].word, array[i].occurrance);
}
}
}
And the compiler says me:
C:\Users\Matteo\Google Drive\Programming\C\lab3\es1\main.c|47|error: incompatible types when assigning to type 'word' from type 'void *'|
I just studied memory allocation so i'm having some trouble with it, especially with structures. If possible, plase link me also some good docs about this subject.
thank you!
In main word *array is a pointer to a structure of type word.
You then pass array, which does not point to anything, to the function array_word_creator.
You then try to assign the pointer returned by malloc to where array is pointing, but it doesn't point anywhere yet, and even if it did, it would be pointing to a word (since it is a word *), so it can't store a pointer, hence the compiler error.
If you want to set the array pointer in main to the result of malloc, you have to pass a pointer to the pointer. int array_word_creator(word **array, FILE *fp), then you would call it by doing array_word_creator(&array, .... ), the your *array = malloc will work.
You want this:
...
arr_lenght = array_word_creator(&array, f_words);
...
int array_word_creator(word **array, FILE *fp)
{
int n, i = 0;
fscanf(fp, "%d", &n);
*array = malloc(n * sizeof(word));
while (fscanf(fp, "%19s", (*array)[i].word) != EOF)
{
i++;
}
initialize(*array, n);
return n;
}
I'm trying to create an array to hold an int, then when another int is to be added increase it in size to hold another int.. and so on..
I know it's not an efficient use of realloc, but it's proof on concept more than anything else. Just to get it working would allow me to optimise it and be able to apply it to something useful. A working example. The problem comes when i call the print function and it just segfaults. Any help would be appreciated.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
typedef char String[100];
void begin(int *);
void add(int *, int);
void print(int *);
int tempcount=0;
int main(void)
{
int *n=NULL;
String menu;
begin(n);
while(true)
{
scanf("%9s", menu);
if(!strcmp("a", menu)) //add
{
int i=0;
scanf("%d", &i);
add(n, i);
}
else if(!strcmp("p", menu)) //print
{
print(n);
}
else if(!strcmp("q", menu)) //quit
{
free(n);
break;
}
}
return 0;
}
void begin(int *n)
{
n=malloc(sizeof(int));
if(n==NULL)
{
printf("Error in malloc!");
return;
}
n[0]=0;
printf("Added %d \n", n[0]);
}
void add(int *n, int numToAdd)
{
static int sizeCount=0;
sizeCount++;
tempcount=sizeCount;
int *temp;
temp=realloc(n, (sizeCount+1) * sizeof(int));
if(temp==NULL)
{
printf("Error in realloc!");
return;
}
n=temp;
n[sizeCount]=numToAdd;
printf("Added %d \n", n[sizeCount]);
}
void print(int *n)
{
int i;
for(i=0; i<tempcount; i++)
{
printf("%d ", n[i]);
}
}
You need to pass a pointer to your pointers in add/begin so they can modify your pointer in main
begin(&n);
...
add(&n, i);
and your definition
void begin(int **n)
{
*n=malloc(sizeof(int));
if(*n==NULL)
{
printf("Error in malloc!");
return;
}
(*n)[0]=0;
printf("Added %d \n", (*n)[0]);
}
and
void add(int **n, int numToAdd)
{
static int sizeCount=0;
sizeCount++;
tempcount=sizeCount;
int *temp;
temp=realloc(*n, (sizeCount+1) * sizeof(int));
if(temp==NULL)
{
printf("Error in realloc!");
return;
}
*n=temp;
(*n)[sizeCount]=numToAdd;
printf("Added %d \n", (*n)[sizeCount]);
}
Right now what you're doing is modifying local copies of your pointer in begin/add, so when you change it in those functions it's not modifying your pointer n in main
Also, fun fact, if you pass NULL as the first parameter to realloc it acts like a malloc, so if you initialize n to NULL, you can simply call add without first doing a begin.
Check your function add - are you sure you update the pointer value?
Try with ** as a parameter - I think it will help.
In this program, I want to sort a list, according to price, and then i use a quick sort to sort the list, in the quick sort, I used the compare of comp_on_price, and then call the quick sort at interface. However, when I run it, it comes up with compile error of too few argument.
Does there have anything to do with the calling method?
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
FILE *fp;
typedef struct book{
double rating;
double price;
double relevance;
int ID;
}B;
B *list;
int read_file(char* infile, int N)
{
int c;
if((fp=fopen(infile, "rb")))
{
fscanf(fp, "%*s\t%*s\t%*s\t%*s\n");
c=0;
while((!feof(fp))&&(c<N))
{
fscanf(fp, "%lf\t%lf\t%lf\t%d\n", &list[c].rating, &list[c].price, &list[c].relevance, &list[c].ID);
c++;
}
fclose(fp);
}
else
{
fprintf(stderr,"%s did not open. Exiting.\n",infile);
exit(-1);
}
return(c);
}
int comp_on_price(const void *a, const void *b)
{
if ((*(B *)a).price < (*(B *)b).price)
return 1;
else if ((*(B *)a).price > (*(B *)b).price)
return -1;
else
return 0;
}
void quicksort(int x[10],int first, int last, int(*comp_on_price)(const void *, const void *))
{
int pivot,j,temp,i;
if(first<last)
{
pivot=first;
i=first;
j=last;
while(i<j)
{
while(x[i]<=x[pivot]&&i<last)
i++;
while(x[j]>x[pivot])
j--;
if(i<j){
temp=x[i];
x[i]=x[j];
x[j]=temp;
}
}/* while*/
temp=x[pivot];
x[pivot]=x[j];
x[j]=temp;
quicksort(x,first,j-1);
quicksort(x,j+1,last);
}
}
void user_interface(int N)
{
// For Part 1 this function calls the sort function to sort on Price only
comp_on_price(N);
// For Part 2 this function
// (1) asks the user if they would like to sort their search results
// (2) asks for the most important field (or key), the next most etc
// (3) calls your sort function
}
void print_results(int N)
{
int i;
if((fp=fopen("top20.txt","w")))
{
for(i=N-1;i>=N-20;i--)
{
printf("%g %g %g %d\n", list[i].rating, list[i].price, list[i].relevance, list[i].ID);
fprintf(fp, "%g %g %g %d\n", list[i].rating, list[i].price, list[i].relevance, list[i].ID);
}
fclose(fp);
}
else
{
fprintf(stderr,"Trouble opening output file top20.txt\n");
exit(-1);
}
}
int main(int argc, char *argv[])
{
int N;
if(argc!=3)
{
fprintf(stderr, "./exec <input_size> <filename>\n");
exit(-1);
}
N=atoi(argv[1]);
list = (B *)malloc(N*sizeof(B));
N=read_file(argv[2], N);
user_interface(N);
print_results(N);
return(0);
}
quicksort(x,first,j-1);
If you take a look at your quicksort function declaration, you'll see it has 4 and not 3 parameters. The last parameter is a pointer to a comparison function.
You should call it like this:
quicksort(x, first, j-1, comp_on_price);
your function
void quicksort(int x[10],int first, int last,int(*comp_on_price)(const void *, const void *))
has 4 input parameter and the last one is a pointer to a function. you can remove it because you did not use it this function