I need to be able to enter array of ints and hold it in a set inside a struct, however for some reason it won't read the numbers into the array:
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#define MAX 100
typedef struct set {
int arr[MAX];
} set;
set SETA;
int read_set(set,...);
void print_set(set);
int main(){
int x;
x=read_set(SETA,2,3,4,-1);
printf("%d numbers were read\n",x);
print_set(SETA);
return 0;
}
void print_set(set s){
int *iptr;
iptr=s.arr;
while(*iptr++){
printf("%d ",*iptr);
}
}
int read_set(set s,...){
va_list ap;
int i=0;
int c=0;
va_start(ap,s);
while( *ap != -1){
s.arr[i++]=va_arg(ap,int);
printf("%d was entered\n",s.arr[i]);
c++;
}
va_end(ap);
return c;
}
the output I get is:
0 was entered
0 was entered
0 was entered
3 numbers were read
and needless to say that print_set prints nothing.
In
while( *ap != -1){
s.arr[i++]=va_arg(ap,int);
printf("%d was entered\n",s.arr[i]);
c++;
}
you increment i when you record the value.
When you try to print s.arr[i] you are one ahead of where you stored the value.
Increment after the print?
while( *ap != -1){
s.arr[i]=va_arg(ap,int);
printf("%d was entered\n",s.arr[i]);
i++;
c++;
}
You function int read_set(set s,...) takes a copy of a set s and puts stuff in it.
By the time you get back to the calling function in main, the set that you copied in is unchanged.
You need to send pointers to variables to change them:
int read_set(set *ps,...)
and the calling code would then need to send the address x = read_set(&SETA, 2, 3, 4, -1); so you can change what's in the set.
An alternative is to return the filled structure.
Two other things to think about.
First, you could declare your set inside main - it has no reason to be global.
And you don't need to captilaise it.
int main() {
set setA; //style/design point. Also don't shout.
//... etc
}
Also, look at your print function.
It uses while (*iptr++), so is checking of 0s or some kind of NULL to stop looping. I can't see any zeros so this needs a re-think. And, do you want to have a set that won't display anything beyond a 0?
Related
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;
}
I need to get this output:
P1 0 3
P2 1 6
P3 4 4
P4 6 2
But instead I am getting this:
0 0 0
0 0 0
0 0 0
0 0 0
I am new to C programming. So, I don't know why I am getting wrong output. This is what I did. I am supposed to store each column in different variable. Because After storing them in different variable I need to do maths calculation for them.
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
#include <math.h>
#include <stdint.h>
#include <stdbool.h>
int main (int argc, char *argv[]) {
FILE *fptr;
fptr = fopen(argv[1], "r");
if (fptr != NULL) {
size_t i;
int SIZE = 1000;
int*x[500];
int*y[500];
int*z[500];
int ch=0;
int l;
int n=0;
char line[100];
while ((ch=fgetc (fptr))!= EOF) {
if (ch=='\n')
n++;
}
printf("Number of lines = %d\n", n);
for (l=0; l<n;++l) {
while(fgets(line,sizeof line,fptr)) {
printf("%s",line);
sscanf(line,"%d %d %d",&x[l],&y[l],&z[l]);
}
}
for (i=0; i<l;++i) {
printf("%d %d %d\n",x[i],y[i],z[i]);
}
fclose(fptr);
return 0 ;
}
I see at least 2 issues.
The fptr has gone to the end of file while counting number of lines. So rewind() the fptr after counting lines, as it has gone up to the end of file. So add rewind(fptr) after first while loop.
You do not need x, y, z as array of pointers, rather just an array. So change them to
int x[500];
int y[500];
int z[500];
Okay, lets sort this out with comments first:
#include<stdio.h>
// i dont think the following includes are nessesary for the given code
//#include<stdlib.h>
//#include <string.h>
//#include <math.h>
//#include <stdint.h>
//#include <stdbool.h>
int main (int argc, char *argv[]) {
FILE *fptr;
// i wonder a little about what youre opening here with argv[1]
// since arrays start counting at 0
// for testing and more understandability maybe just put the file
// where your code is and deliver its filename as a string?
fptr = fopen(argv[1], "r");
if (fptr != NULL) {
// whats that? you use it as a counting variable, make it int
// not size_t
size_t i;
// its not good practive to have a variable in capitals
// if you wanna make it a constant, you should define it
// at the beginning of the code, right after your includes
int SIZE = 1000;
// dont use pointers (these -> "*") here! Maybe you mix up
// dynamic array declaration (which requires using malloc() and
// no brackets like "int * dynArray;") with static arrays
// correct usage would be: int x[500]; thats it
int*x[500];
int*y[500];
int*z[500];
int ch=0;
// just a hint for more readability: use "j" instead of "l" but
// thats really up to you :D
int l;
int n=0;
char line[100];
// here you loop through your file char by char and just count
// the lines. Why dont pick the chars on the fly and actually
// write something into your defined arrays x, y, z ?
// some additional conditions (if) may do the trick
while ((ch=fgetc (fptr))!= EOF) {
if (ch=='\n')
n++;
}
printf("Number of lines = %d\n", n);
// sizeof is a function, so youre missing the parentheses
// and above that, you already know the size of your line array
// because its statically defined to hold 100 * sizeof(char)
// my suggestion: trash this entire loop and rethink the previous
for (l=0; l<n;++l) {
while(fgets(line,sizeof line,fptr)) {
printf("%s",line);
sscanf(line,"%d %d %d",&x[l],&y[l],&z[l]);
}
}
// cool loop. but there was no input to x, y, z except the first
// element of your line array, which seems to hold just a 0
// so everythings correct here, the mistake occured before
for (i=0; i<l;++i) {
printf("%d %d %d\n",x[i],y[i],z[i]);
}
//nice, thats important :)
fclose(fptr);
return 0 ;
}
i hope it helps you sort out things and may guide to a clearer question which maybe answeres itself? :D
My program consists of a Menu, where you can select 1 of 2 options.
The second is just to exit the program. The first, however, is where you can find a specific sequence of bits that you choose, in a separate ".txt" file with 100.000 lines.
It does what I want the first time, and then returns to the Menu.
The problem is when the user goes for a second (or more) search. The program prints on screen random information.
It seems like I didn't do a "reset" of the resources, memory or values on the first search.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
char ID[8];
char content[2048];
int distance;
} DATA;
void search(){
FILE *f;
DADO *z=NULL;
long int tot=0;
int a;
int c;
int i;
int j=1;
int k=0;
char e;
char b[2048];
printf("\n");
f=fopen("DANGER_DB_LARGE.txt", "r");
printf("\n");
printf("How many results do you wish?\n");
scanf("%d",&a);
printf("Introduce the sequence:\n");
scanf("%s",b);
c=strlen(b);
printf("\n");
z=(DATA*)realloc(z,(++tot)*sizeof(DATA));
while(e!=EOF){
e=fgetc(f);
if(k<8){
z[tot-1].ID[k]=e;
}
else if(k==8 && e=='\t'){
continue;
}
else if(k>=9 && e!='\n'){
z[tot-1].content[k-9]=e;
}
else if(e=='\n'){
k=(-1);
z=(DATA*)realloc(z,(++tot)*sizeof(DATA));
}
k++;
}
for(i=1; i<=tot; i++){
distance(z,i,c,b);
}
free(z);
fclose(f);
}
I proceed to store the ID and content of every single one of those 100.000 lines of text. I end the function by doing free(z), but when I search again the program just prints random stuff.
Use of uninitialised variables without an intervening assignment is undefined behaviour. It may work on the first Wednesday of every month, on the first time through the loop, only when the boss is looking, ...
int e; // originally was char
//...
while (e != EOF) { // uninitialised, no intervening assignment
Realloc returns void by the way
void *realloc(void *ptr, size_t size)
plus it takes a pointer as input so its pass by reference.
update: This function returns a pointer to the newly allocated memory, or NULL if the request fails.
my bad.
This question already has answers here:
How to find the size of an array (from a pointer pointing to the first element array)?
(17 answers)
Closed 6 years ago.
Ok, so the idea of the task I have (I am the student) is to allow user to insert a string of words in this form: num1_num2_num3..._numN. The code should create an array X, give it memory dynamically and then I should fill X with numbers from string user inserted. Simple as that. Well, in the function stringuniz() I thought I had it all figured out but it simply wont work. It gets the first number well but it then stops and I think its because of the break. Break behaves (if I am right) like it breaks the entire code and not just the loop. Do you guys have an idea why is this happening?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void stringuniz(char *);
int *x;
int main(){
char s[50];
int i;
puts("Unesite string brojeva u formatu br1_br2_...brN: ");
gets(s);
stringuniz(s);
for(i=0;i<(sizeof(x)/sizeof(int));i++)
printf("%d",x[i]);
}
void stringuniz(char *s){
int duz,c=0,i,j,k=0,m=0;
char b[10];
duz=strlen(s);
for(i=0;i<duz;i++)
if(s[i]=='_')
c++;
x=(int*)malloc((c+1)*sizeof(int));
if(x==NULL) exit(1);
for(i=0;i<c+1;i++){
for(j=m;j<duz;j++){
if(s[j]!='_'){
b[k++]=s[j];
m++;
}
else{
b[k]='\0';
x[i]=atoi(b);
k=0;
m++;
break;
}
}
}
}
This
(sizeof(x)/sizeof(int)
won't give you the size of the array. sizeof(x) is the bytesize of int* (likely 4 or 8).
You'll need to remember the size as implied by the number of _ in the string.
Also you have some off-by-one errors in there and for future reference, you might want to choose more descriptive variable names for code you decide to post publicly.
The code worked for me once I changed it to:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void stringuniz(char *);
int *x;
int x_size = 0;
int main(){
char s[50];
int i;
puts("Unesite string brojeva u formatu br1_br2_...brN: ");
fgets(s,50,stdin);
stringuniz(s);
for(i=0;i<x_size;i++)
printf("%d\n",x[i]);
}
void stringuniz(char *s){
int duz,c=0,i,j,k=0,m=0;
char b[10];
duz=strlen(s);
for(i=0;i<duz;i++)
if(s[i]=='_')
c++;
x=malloc((c+1)*sizeof(int));
x_size = c+1;
if(x==NULL) exit(1);
for(i=0;i<=c+1;i++){
for(j=m;j<=duz;j++){
if(s[j]!='_' && s[j]!='\0'){
b[k++]=s[j];
m++;
}
else {
b[k]='\0';
x[i]=atoi(b);
k=0;
m++;
break;
}
}
}
}
void stringuniz(char *);
int *x;
int main(){
[...]
}
void stringuniz(char *s){
[...]
}
I don't know why many ppl teach it this way, but there is absolute no use in having main somewhere in the middle of a source file, and putting it at the end also allows you to get rid of the forward declarations. So, I would write it this way:
int *x;
void stringuniz(char *s){
[...]
}
int main(){
[...]
}
Then you should start using the space character more.
stringuniz(s);
for(i=0;i<(sizeof(x)/sizeof(int));i++)
printf("%d",x[i]);
In a comment, alain already pointed out, that sizeof(x) will return the size of a pointer. So, you need a different way to figure out the size of the array. One way is to add a variable size_t x_len; besides int * x;. Also, you should use curley brackets even for one line statements, believe me, not only makes it the code more readable, it also prevents introducing bugs on later changes.
for (i = 0; i < x_len; i++) {
printf("%d", x[i]);
}
.
void stringuniz(char *s){
int duz,c=0,i,j,k=0,m=0;
char b[10];
b will hold the word the user enters. If his word is longer then 9 characters, you get a buffer overflow here.
duz=strlen(s);
for(i=0;i<duz;i++)
if(s[i]=='_')
c++;
You are counting the number of words here. So, please use more descriptive names like num_words instead of c. BTW: This is the x_len mentioned above.
x=(int*)malloc((c+1)*sizeof(int));
No need to cast return value of malloc. Actually it might hide bugs. Also, I would use sizeof(*x) instead of sizeof(int), because if you change the type of x, in your statement, you also would have to change the malloc call. In my statement, the malloc call doesn't need to be touched in any way.
x = malloc((c+1) * sizeof(*x));
if(x==NULL) exit(1);
for(i=0;i<c+1;i++){
for(j=m;j<duz;j++){
if(s[j]!='_'){
b[k++]=s[j];
You are constantly overwriting b with the next word being read. Since you're not using it anyway, you can just skip this line.
m++;
}
else{
b[k]='\0';
x[i]=atoi(b);
k=0;
m++;
break;
And this break; only breaks out of the innermost for (j-loop.
}
}
}
}
Basically, why does it not just print the integers that are entered. Right now it just prints garbage value, but I do not know why it cannot access the values stored after it leaves the function. It only seems to get messed up after leaving the getIntegersFromUser function. If I run the for loop in the getIntegers function it does it properly, but why not in the main function?
Thanks in advance for your help.
#include <stdio.h>
#include <stdlib.h>
void getIntegersFromUser(int N, int *userAnswers)
{
int i;
userAnswers =(int *)malloc(N*sizeof(int));
if (userAnswers)
{ printf("Please enter %d integers\n", N);
for (i=0;i<N; i++)
scanf("%d", (userAnswers+i));
}
}
int main()
{
int i, M=5;
int *p;
getIntegersFromUser(M, p);
for (i=0;i<5;i++)
printf ("%d\n", p[i]);
return 0;
}
Also, this is a homework question, but it's a "Bonus Question", so I'm not trying to "cheat" I just want to make sure I understand all the course material, but if you could still try to give a fairly thorough explanation so that I can actually learn the stuff that would be awesome.
Pointers are passed by value. The function is using a copy of your pointer, which is discarded when the function ends. The caller never sees this copy.
To fix it, you could return the pointer.
int *getIntegersFromUser(int N)
{
int *userAnswers = malloc(...);
...
return userAnswers;
}
/* caller: */
int *p = getIntegersFromUser(M);
Or you could pass your pointer by reference so the function is acting on the same pointer, not a copy.
void getIntegersFromUser(int N, int **userAnswers)
{
*userAnswers = (int *) malloc(N*sizeof(int));
...
}
/* caller: */
int *p;
getIntegersFromUser(N, &p);