Can't more than two strings compare? - c

If we compared integers we would assign one of them as the largest/smallest one.
However, when I try comparing more than two strings, I can't manage assaigment.
In my code "for loop" compares two of the strings. This is good method but I need to compare one of them to the others individually. (I can predict that I need to use two for loop, but also I can't implement) What is your suggestions?
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct wordSorting
{
char name[15];
int i = 0;
};
int main()
{
wordSorting *wordElement = (wordSorting *)malloc(sizeof(wordSorting));
wordElement = (wordSorting *)malloc(sizeof(wordSorting));
printf("-- Enter three person name --\n\n");
for (wordElement->i = 0; wordElement->i < 3; wordElement->i++)
{
printf("Enter %d. person name: ", wordElement->i + 1);
scanf("%s", wordElement[wordElement->i].name);
}
printf("\n");
for (wordElement->i = 0; wordElement->i < 3; wordElement->i++)
{
if ((strcmp(wordElement[wordElement->i].name, wordElement[wordElement->i + 1].name))<0)
{
printf("%s", wordElement[wordElement->i].name);
}
}
}

First
typedef struct wordSorting
{
char name[15];
int i = 0;
};
Members of typedef/struct cannot be initied.
That is not the way to define a typedef, change it as:
typedef struct
{
char name[15];
int i;
}wordSorting;
Second:
wordElement = (wordSorting *)malloc(sizeof(wordSorting));
makes no sense. malloc returns void pointer, and you already init your variable at the first element in the first line of code.
And, as someone edited: do not cast malloc return, please.
Third, :
wordSorting *wordElement = (wordSorting *)malloc(sizeof(wordSorting));
wordElement = (wordSorting *)malloc(sizeof(wordSorting));
printf("-- Enter three person name --\n\n");
for (wordElement->i = 0; wordElement->i < 3; wordElement->i++)
{
printf("Enter %d. person name: ", wordElement->i + 1);
scanf("%s", wordElement[wordElement->i].name);
}
You are allocating space for one element, no array are defined then wordElement[wordElement->i].name is undefined Behaviour.
Finally
I don't know what compiler are you using, but gcc cannot compile such a bad code full of errors...
Suggestion.
What I think you need is to use array, but you must allocate the number of member you need, by:
wordSorting *wordElement = malloc(sizeof(wordSorting)*num_of_elements);
or simply, using a local array:
wordSorting wordElement[num_of_elements];

Related

Problem reading in string in C for dynamic number inputs

I'm a Noob, struggling with C. I'm having a hard time wrapping my head around pointers, arrow -> and dot . notation. I am working on a very simple program that has 1 struct, but I am unsure of how to get users to input strings without using the <cs50.h> header (which I need to understand for the harder problem I am also trying to wrap my head around).
//#include <cs50.h>
#include <stdio.h>
#include <string.h>
// create a struct, call it pupils
typedef struct
{
char *name;
char *dorm;
}
pupils;
int main(void)
{
// Allocate space for students - generally dynamic, here static
int enrollment = 2;
// create variable 'idinfo', which contains (enrollment) number of structs of type pupils
pupils idinfo[enrollment];
// Prompt for students' names and dorms
for (int i = 0; i < enrollment; i++)
{
// Not the way to do this given various error codes.....
char idinfo[i].Name[20];
char Dorm[20];
// gets idinfo[i].Name
scanf("%s", idinfo[i].Name);
//idinfo[i].name = printf("%s", Name);
// Below syntax works fine when <string.h> header included
idinfo[i].dorm = get_string("Dorm: ");
}
// Print students' names and dorms
for (int i = 0; i < enrollment; i++)
{
printf("%s is in %s.\n", idinfo[i].name, idinfo[i].dorm);
}
}
Assuming you do not want to use the cs50 magic, you will have to allocate and deallocate strings. From your code I will also assume that the input strings are supposed to be shorter than 20 characters. The following code does not even ensure that it is true but will not crash either but will simply give unexpected results.
Code could be:
int main(void)
{
// Allocate space for students - generally dynamic, here static
int enrollment = 2;
// create variable 'idinfo', which contains (enrollment) number of structs of type pupils
pupils idinfo[enrollment];
// Prompt for students' names and dorms
for (int i = 0; i < enrollment; i++)
{
// allocate memory for idinfo[i] pointers:
idinfo[i].name = malloc(20);
scanf("%19s", idinfo[i].name);
idinfo[i].dorm = malloc(20);
scanf("%19s", idinfo[i].dorm);
}
// Print students' names and dorms
for (int i = 0; i < enrollment; i++)
{
printf("%s is in %s.\n", idinfo[i].name, idinfo[i].dorm);
}
// free allocated memory
for (int i = 0; i < enrollment; i++)
{
free(idinfo[i].name);
free(idinfo[i].dorm);
}
}
You probably want something like this:
#include <cs50.h> // needed for get_xxx functions and other cs50 stuff
...
// Prompt for students' names and dorms
for (int i = 0; i < enrollment; i++)
{
idinfo[i].name = get_string("Name: ");
idinfo[i].dorm = get_string("Dorm: ");
}
But this should be covered in the documentation you were given.
My advice is not using scanf at all but using only the cs50 get_xxx input methods.
And beware: the cs50 string is not a real "string" type but merely the same thing as char *.
Thanks to Serge, I was able to get my code compiling, which is below.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// create a struct, call it pupils
typedef struct
{
char *name;
char *dorm;
}
pupils;
int main(void)
{
// Allocate space for students - generally dynamic, here static
int enrollment = 2;
// create variable 'idinfo', which contains (enrollment) number of structs of type pupils
pupils idinfo[enrollment];
// Prompt for students' names and dorms
for (int i = 0; i < enrollment; i++)
{
// allocate memory for idinfo[i] pointers:
idinfo[i].name = malloc(20);
idinfo[i].dorm = malloc(20);
printf("Enter student %d's Name ", i+1);
scanf("%19s", idinfo[i].name);
printf("Enter student %d's dorm ", i+1);
scanf("%19s", idinfo[i].dorm);
}
// Print students' names and dorms
for (int i = 0; i < enrollment; i++)
{
printf("%s is in %s.\n", idinfo[i].name, idinfo[i].dorm);
}
// free allocated memory
for (int i = 0; i < enrollment; i++)
{
free(idinfo[i].name);
free(idinfo[i].dorm);
}
}

scanf doesn't take all in inputs

I supposed to perform a project which allocate N bytes of memory of struct person
and scanning f every person's name initial_money and some other variables
the problem for me when i run the code is that it is terminating at some point of taking input process and i don't why
also this problem faced me yesterday in code forces contest
#include <stdio.h>
#include <stdlib.h>
struct person
{
char name[15];
int initial_money;
int g;
int final_money;
int money;
};
int main()
{
int NP,i,j;
char target1[15];
scanf("%d",&NP);
struct person *p=malloc(NP*sizeof(struct person));
for(i=0;i<NP;i++)
{
scanf("%s",(p+i)->name);
}
for(i=0;i<NP;i++)
{
scanf("%s",target1);
for(j=0;j<NP;j++)
{
if((p+j)->name==target1)
{
scanf("%d%d",(p+j)->initial_money,(p+j)->g);
(p+j)->final_money=(p+j)->initial_money%(p+j)->g;
}
}
}
for(i=0;i<NP;i++)
{
printf("%s %d %d %d",(p+i)->name,(p+i)->initial_money,(p+i)->g,(p+i)->final_money);
}
return 0;
}
The scanf function need pointers for inputed values.
The line:
scanf("%d%d",(p+j)->initial_money,(p+j)->g);
Should be:
scanf("%d %d",&(p+j)->initial_money,&(p+j)->g);
When comparing strings you usually can't compare pointers directly:
if((p+j)->name==target1)
shoul be:
if(strcmp((p+j)->name, target1) == 0)

Getting multiple struct entries from stdin

I am trying to get multiple entries for my struct via the keyboard. I think I am wrong inside of scanf but I am not sure where I am wrong. Thanks!
Here is what I have:
#include <stdio.h>
#include <math.h>
int main()
{
//define the structure
struct course
{
char title[20];
int num;
} ;
// end structure define
//define the variable
struct course classes;
printf("Enter a course title and course number");
scanf("%s %d", classes[3].title, &classes.num);
return 0;
}
Fix the code as Carl said and it works fine:
#include <stdio.h>
int main()
{
struct course
{
char title[20];
int num;
} ;
struct course class;
printf("Enter a course title and course number");
scanf("%s %d", class.title, &class.num);
printf("%s %d", class.title, class.num);
return 0;
}
There are a couple issues.
You have this struct called "classes", but it has only 1 entry - you're accessing the 3rd entry so you're running off the end.
Also, Title is 20 bytes long, but if you enter something larger in scanf(), it will just overflow. The basic scanf() structure looks ok though.
I would set it up more like this:
#include <stdio.h>
#include <math.h>
#define MAX_CLASSES 50 // how big our array of class structures is
int main()
{
//define the structure
struct course
{
char title[20];
int num;
} ;
// end structure define
//define the variable
struct course classes[MAX_CLASSES];
int nCurClass = 0; // index of the class we're entering
bool bEnterMore = true;
while (bEnterMore == true)
{
printf("Enter a course title and course number");
scanf("%s %d", classes[nCurClass].title, &classes[nCurClass].num);
// if user enters -1 or we fill up the table, quit
if (classes[nCurClass].num == -1 || nCurClass > MAX_CLASSES-1)
bEnterMore = false;
}
}
That's the basic idea. Another improvement that could be made would be checking the length of the course title before assigning it to classes[].title. But you need something to do ;-)

dynamic array of structs in C

I am trying to learn about structs, pointers, and dynamic arrays in C. I don't understand how to create a dynamic array of structs using pointers. My code doesn't work, and I don't know what's wrong with it. I have seen several examples of dynamic arrays, but non with structs. Any help would be appreciated. Please give some explanation, not just code snippets as I do want to understand not just solve this problem.
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
struct *struct_array;
int i,m,n,p;
struct data
{
char inputA[20];
char inputB[20];
};
struct data get_data()
{
struct data thisdata;
printf("Please enter input A\n");
scanf("%s", thisdata.inputA);
printf("Please enter input B\n");
scanf("%s", thisdata.inputB);
return thisdata;
}
void Output(struct data struct_array, int n)
{
int index = 0;
for(i = 0; i<n ;i++)
{
printf("%s ", struct_array[i].inputA);
printf("%s ", struct_array[i].inputB);
}
}
void resizeArray(int n)
{
struct_array = (int*)realloc(n*sizeof(int));
}
void mainMenu()
{
printf("Please select from the following options:\n");
printf("1: Add new students to database\n");
printf("2: Display current student database contents\n");
printf("3: exit the program\n");
scanf("%d", &p);
if(p == 1)
{
printf("Please enter the number of students to register:\n");
scanf("%d", &n);
resizeArray(n);
for(i = n; i<n ;i++)
{
struct_array[i] = get_data();
}
}
else if(p == 2)
{
Output(struct_array, n);
}
else
{
free(struct_array);
exit(0);
}
}
int main()
{
struct_array = (int*)realloc(2*sizeof(int));
mainMenu();
}
You have several errors in your source code:
struct *struct_array; (l. 5)
What does it mean? Did you want to write struct data *struct_array?
printf("%s ", struct_array[i].inputA); (l.32 & l. 33)
The argument struct_array masks the global declaration, and it is not an array. Why did you add this argument?
struct_array = (int *)realloc(n * sizeof(int)); (l. 39)
You have forgotten an argument. Did you want to use malloc instead? Besides, the cast is not necessary (and incorrect!).
Unless you are using an hosted environnment and C99/C11, you should return a value from main.
Your variable index is not used. Why did you declare it?
for(i = n; i < n; i++) (l. 53)
You won't have any iteration here...
The following code works as expected.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* TODO: Avoid global variables. */
struct data *struct_array;
struct data {
char inputA[20];
char inputB[20];
};
/*
* TODO: Try to avoid passing your structure (40 bytes + padding)
* without pointer.
*/
struct data get_data(void)
{
struct data thisdata;
printf("Please enter input A\n");
/* TODO: Avoid using `scanf` for human inputs. */
scanf("%s", thisdata.inputA);
printf("Please enter input B\n");
scanf("%s", thisdata.inputB);
return thisdata;
}
void Output(size_t n)
{
size_t i;
for (i = 0; i < n; i++) {
printf("%s ", struct_array[i].inputA);
printf("%s ", struct_array[i].inputB);
}
}
void resizeArray(size_t n)
{
/* TODO: Handle reallocations errors. */
struct_array = realloc(struct_array, n * sizeof *struct_array);
}
void mainMenu(void)
{
size_t i, n;
int p;
/* TODO: Use a loop ? */
printf("Please select from the following options:\n");
printf("1: Add new students to database\n");
printf("2: Display current student database contents\n");
printf("3: exit the program\n");
scanf("%d", &p);
switch (p) {
case 1:
printf("Please enter the number of students to register:\n");
scanf("%u", &n);
resizeArray(n);
for (i = 0; i < n; i++)
struct_array[i] = get_data();
break;
case 2:
Output(n);
break;
}
}
int main(void)
{
struct_array = malloc(2 * sizeof(int));
mainMenu();
free(struct_array);
return 0;
}
Your definition
struct *struct_array;
is erroneous. You must use the name of your type, the data.
struct data *struct_array;
This way you can allocate the array
struct_array = malloc(MaxNumElements * sizeof(struct data));
and later you should free the memory
free(struct_array);
EDIT: Type definition must occur before the var declaration.
struct data ....
struct data* your_variable;
P.S. If you do not want to type struct keyword each time you use the data type, use the typedef:
typedef struct data_s
{
char inputA[20];
char inputB[20];
} data;
Do you know how to use typedef?
I would suggest it, makes your code easier to understand and you won't have to be typing the word struct a thousand times. Also you could treat the new type similar to the primitive types (ints, chars, etc), just don't forget to use the dot (.) to access the individual fields you might want.
You could type for instance:
typedef struct{
char inputA[20];
char inputB[20];
} data;
Now you could declare variables like this:
data data_variable;
data *pointer_to_data;
And to you could allocate memory as follows:
pointer_to_data = (data*) malloc(sizeof(data)* N);
where N is the amount of struct data you want to allocate. Same works for realloc.
struct_array = (int*)realloc(2*sizeof(int));
By the above statement you are trying to assign address of an int to a pointer of type struct data.
You need to use:
struct_array = (struct data*)realloc(2*sizeof(struct data));

Assigning Values to Variables Within Structs Through Pointers in C

Ok so I'm sure there's a simple fix that I'm missing, but right now my code is causing a segment fault on the line "A[i]->key = 0;." The Record* Item part is a necessity for the program, so I need to make it work this way for an assignment I'm working on, however if I do change it so that Item becomes a non-pointer typedef of Record, then I can use A[i].key no problem. I just need a nudge in the right direction so that I can make standInput correctly assign values to an array of pointers to records. Thanks!
Item.h:
#include "stdio.h"
#include "stdlib.h"
typedef int keyType;
struct Record
{
keyType key;
int other;
};
typedef struct Record* Item;
void standInput(Item *A, int n)
{
int i, input;
for(i = 0; i <= n-1; i++)
{
A[i]->key = 0;
printf("%d ", A[i]->key);
}
}
Main:
#include "stdio.h"
#include "stdlib.h"
#include "Item.h"
int main()
{
int n;
Item *A;
printf("Enter a length for the array: ");
scanf("%d", &n);
A = (Item*)malloc(n * sizeof(Item));
standInput(A, n);
return 0;
}
The values in A are all uninitialized, but you're using them as struct Record pointers anyway. If you want to have A continue holding pointers (rather than the structs directly), then you need to allocate space for A and for each item pointed to by A.
Note that Item is already a pointer!
You have to allocate space for the struct, not for the pointer:
A = (Item)malloc(n * sizeof(struct Record));
Note: If the typedef for pointer confuses you, don't use it ;)
A[i]->key means that A[i] is a pointer, but you just allocated an array, so use A[i].key.
Note: you have to change the type of A accordingly.
2nd solution: if you want A[i] to be a pointer, you have to fist allocate space for the pointers (as you do now), then for each pointer (in a loop) allocate space for the struct.
Your structure name is Record not Item. So you should use sizeof(struct Record).
Do it this way:
int main()
{
int n, i;
Item *A;
printf("Enter a length for the array: ");
scanf("%d", &n);
A = (Item*)malloc(n * sizeof(Item));
for(i=0; i<n; i++){
A[i] = (Item)malloc(sizeof(struct Record));
}
standInput(A, n);
return 0;
}

Resources