scanf does not work - c

im implementing a program that reads student id and names from stdin or file, and make them ordered by name and ordered by number. The funny thing is i cant understand why but scanf doesnt work. Here is my code while using scanf:
int n=0;
while(n<SIZE){
scanf("%d %s\n",&std_array[n].id, std_array[n].name);
n++;
}
for(int i=0; i<SIZE; i++)
printf("%d %s\n",std_array[i].id,std_array[i].name);
and here is my struct:
struct Student {
char *name;
int id;};
when i read from file and print them the out put is:
> 12586546 (null) 0 (null) 0 (null) 0 (null) 0 (null) 0 (null) 0 (null)
> 0 (null) 0 (null) 0 (null)
although file have some numbers and names like 21456764 john 45797654 fred etc. , its doesn't read successfully.
NOTE: i know the way we fix struct like you guys suggested but i must learn the way to do this with char pointer...

When doing this:
struct Student {
char *name; // This does not allocate memory
int id;};
Here, name is a pointer, with no allocated memory, behaving like an uninitialized literal string.
Trying to modify it creates undefined behaviour.
Replace with:
struct Student {
char name[50];
int id;};
or
struct Student {
char name[] = "Initial value gives maximum length. Do not write more!";
int id;};

This allocates memory to the pointer as needed. An intermediate variable is used to hold the string then only enough memory plus 1 for the terminating '\0' is allocated in the struct.
int n=0;
char name[100];//longest possible name
while(n<SIZE && ( scanf("%d%99s",&std_array[n].id, name) == 2)) {// successfully scanned two items
std_array[n].name = malloc ( strlen ( name) + 1));
if ( std_array[n].name == NULL) {
printf ( "malloc failed\n");
// break or return or exit(1) as appropriate
}
strcpy ( std_array[n].name, name);
n++;
}
for(int i = 0; i < n; i++)
printf("%d %s\n",std_array[i].id,std_array[i].name);
Eventually you will want to free the memory
for ( i = 0; i < n; i++) {
free ( std_array[i].name);
}

Point 1
Allocate memory to name before using it. Otherwise, if used uninitialized, it does not point to any valid memory to read from or write into. You can use malloc() to allocate memory. Also, once done, don't forget to free() it once you're done using the memory.
Point 2
Remove the \n from scanf().

This is the corrected code
struct Student
{
char name[20];
int id;
};
struct Student std_array[SIZE];
int n=0;
while(n<SIZE)
{
scanf("%d %s", &std_array[n].id, std_array[n].name);
n++;
}
n=0;
while(n<SIZE)
{
printf("%d %s\n", std_array[n].id, std_array[n].name);
n++;
}
Hope this helps...,

as user3121023 told to me, it worked. fixed code is following:
struct Student {
char *name;
int id;
};
struct Student std_array[SIZE];
int cmpfunc (const void * a, const void * b);
struct Student *order_by_number(struct Student *array);
int main(int argc, char **argv){
int n=0;
char name[100];
while(n<SIZE){
scanf("%d %s\n",&std_array[n].id, name);
std_array[n].name = malloc(strlen(name)+1);
strcpy(std_array[n].name ,name);
n++;
}
for(int i=0; i<SIZE; i++)
printf("%d %s\n",std_array[i].id,std_array[i].name);
order_by_number(std_array);
for(int i=0; i<SIZE; i++)
printf("%d %s\n",std_array[i].id,std_array[i].name);
}
im done, ty guys for helping me. CASE CLOSED :)

Related

Problem with pointer in array of structs in C

A problem stops the program working correctly. I guess it is related with using pointer in array of structs. Despite trying many ways, nothing could find out:
#include <stdio.h>
typedef struct {
char* courseName;
char* courseDate;
double grade;
}EXAM;
int main() {
double averageGrade = 0;
EXAM *exams[5];
for(int i = 0; i < 5; i++){
printf("Please enter course name:\n");
scanf("%s", exams[i]->courseName);
printf("Please enter course date:\n");
scanf("%s", exams[i]->courseDate);
printf("Please enter course grade:\n");
scanf("%lf", &exams[i]->grade);
averageGrade += exams[i]->grade;
}
averageGrade /= 5;
printf("Your average grade is: %.1lf.", averageGrade);
return 0;
}
1:
typedef struct {
char* courseName;
char* courseDate;
double grade;
}EXAM;
Having defined courseName and courseDate as 'char *' means that they are only pointers. Pointers that without any allocation point to either NULL or more probably to garbage. How to fix it?
Either define your structure with statically allocated char arrays, like:
typedef struct {
char courseName[41];
char courseDate[41];
double grade;
}EXAM;
or allocate them dynamically before signing anything into them:
for (int i = 0; i < 5; i++) {
exams[i]->courseName = (char *) calloc(41, sizeof(char));
exams[i]->courseDate = (char *) calloc(41, sizeof(char));
}
In both cases you should make sure, that user doesn't overflow this fields so instead of "%s" in scanfs I would suggest using "%40[^\n]", which is simply Get up to 40 characters from user until you find a '\n' character (user hits enter).
In addition in first case, you should make sure that both strings are null-terminated strings, a simple way to do it is to set zeros in all tables.
memset(exams, 0, sizeof(EXAM)*5);
2:
EXAM *exams[5];
This are also only pointers. That unallocated point to NULL or garbage. Go with either:
EXAM exams[5];
and use '.' instead of '->'.
or allocate them:
for (int i = 0; i < 5; i++) {
exams[i]= (EXAM *) calloc(1, sizeof(EXAM));
}
EXAM[*] points to unallocated memory:
To create an array of 5 exam objects do:
EXAM exams[5]; // Note there is no * character.
If the pointer is necessary for some reason, then you will need to allocate space for these objects:
EXAM *exams[5];
for (int i=0; i<5; i++) {
exams[i] = calloc(1, sizeof(EXAM));
}
You also need to allocate space for the strings:
In C, when you use scanf on a %s, the space for that string must already be allocated.
So you should either use char courseName[256];, allocate sufficient space on the heap for the string, or use functions like getline() which will allocate the space for you.

Don't know how to call function

I am writing a search function in C which uses pointers and structs. Search is possible by name using an array called contatcs with ten entries. The array has already been initialized and populated and works as intended.
I have tried to fix the problem by restructuring my code, but it only made matters worse. Maybe there is some flaw in the design logic that I cannot find.
typedef struct
{
char streetname[150];
char city[50];
int zipcode;
}address;
typedef struct
{
char name[50];
int age;
address homeaddress;
}person;
int search (char* name, person *contacts, int size);
[...] // initialization and population of array omitted
int search (char *name, person *contacts, int size)
{
int i;
printf("Input name: ");
char userin = scanf("%s", name);
for(i = 0; i < size; i++)
{
if (strcmp(contacts[i].name, &userin) == 0)
{
printf("Name: %s;", contacts[i].name);
printf(" Age: %d;", contacts[i].age);
printf(" Adress: %s, ", contacts[i].homeaddress.streetname);
printf("%s, ", contacts[i].homeaddress.city);
printf("%d\n", contacts[i].homeaddress.zipcode);
}
}
return 0;
}
I am just trying to call the function. But every time I try to do so, it just doesn't work. I know this question is rather basic, but I can't seem to find the solution.
char userin = scanf("%s", name);
for(i = 0; i < size; i++)
{
if (strcmp(contacts[i].name, &userin) == 0)
You can not use strcmp with a char, userin must be a NUL terminated array of chars
And as pointed out by #JohnBollinger in comments, it seems you want to compare the name, not the result of scanf

segmentation fault using malloc

I'm new to C, so this may be a silly question to ask:
What I want to do here is to input the data to the array of pointers to a structure and then print it out. But I get a segmentation fault when running into the insert function.
Below is my code
common.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct book * Book;
struct book{
int id;
char *name;
};
extern int b_insert(Book *b, int id, char *name);
extern int b_print(Book books[], int len);
insert.c
#include "common.h"
int b_insert(Book *b, int id, char *name){
Book p;
p = (Book)malloc(sizeof(struct book));
p->id = id;
strcpy(p->name, name);
*b = p;
printf("success insert book:\n");
printf("\tID: %d Name: %s\n", (*b)->id, (*b)->name);
return 0;
}
int b_print(Book books[], int len){
int i;
printf("Book List\n");
for(i=0; i<len; i++){
printf("books[%d] = ID: %d, Name: %s\n", i, books[i]->id, books[i]->name);
}
return 0;
}
main.c
#include "common.h"
#define MAX 2
int main(){
Book books[MAX];
Book *b=books;
int i;
int id;
char name[10];
for(i=0; i<MAX; i++){
printf("please input new books info\n");
printf("ID: ");
scanf("%d", &id);
printf("Name: ");
scanf("%s", name);
if(b_insert(b, id, name) == -1){
printf("fail to insert\n");
}
b++;
}
b_print(books, MAX);
return 0;
}
Main problem:
Allocate memory for p->name before using
strcpy(p->name, name);
using malloc:
p->name = malloc(10); //Or some other size
Other problems:
Remove the cast here:
p = (Book)malloc(sizeof(struct book));
Why? Here is the answer
if(b_insert(b, id, name) == -1){ will never be true.
Check the result of malloc to check if it was successful in allocating memory.
Check the return value of all the scanfs to see if it was successful in scanning data.
Add a length modifier to the second scanf to prevent buffer overflows:
scanf("%9s", name); /* +1 for the NUL-terminator */
You're not allocating space for name:
int b_insert(Book *b, int id, char *name){
Book p;
p = malloc(sizeof(struct book));
if (p != NULL)
{
p->name = malloc(strlen(name)+1); // It allocates space where the input name will be copied.
if (p->name != NULL)
{
p->id = id;
strcpy(p->name, name);
*b = p;
printf("success insert book:\n");
printf("\tID: %d Name: %s\n", (*b)->id, (*b)->name);
}
else return -1; // No space to allocate string
}
else return -1; // No space to allocate struct
return 0;
}
As mentioned before, allocate space for p->name. You should probably also use something different to read the book title, either scanf format %ms with a pointer to a char pointer, or %9s with your buffer, otherwise the title "war or peace" will also result in a segfault.
Here you create a static variable and the space for it is allocated automatically.
Book p;
You can allocate a space manually when you assign it to pointer, in this line it's not pointer but static variable.
p = (Book)malloc(sizeof(struct book));
What's more if you want to refer to attribute of static variable you should use "." instead of "->". So you have two option. Create a pointer and allocate a space for the structure and then you "->" oraz create static variable.
p->id = id;

How to dynamically allocate a two dimensional array of pointers ? (C)

I have an assignment to make a dictionary.
It will contain an x amount of words and their definitions (input by user).
Instructions say that the dictionary should be of type char*** (2D array of pointers=arrays=strings), but I've got absolutely no idea of how to dynamically allocate the size of the array. it should have 2 lines, 1 for words and another 1 for their definitions, and the number of columns is decided by how many words are in the dictionary. While looking for help online i came up with this:
char** AllocateArray(int line, int column)
{
char** pArray=(char**)malloc(line*sizeof(char*));
int i;
for(i=0;i<2;i++)
pArray[i]=(char*)malloc(column*sizeof(char));
return pArray;
}
What changes should i make in the code for it to work with my char*** ?
Using Visual studio 2012
Edit:
I have a problem with this right now:
void inputString(char* p1)
{
char buffer[80];
printf("\nEnter a word:");
scanf("%s",buffer);
p1=(char*)malloc(strlen(buffer)+1);
if(p1!=NULL)
{
strcpy(p1,buffer);
free(buffer);
}
}
it crashes right after i input a word. the char* that the function receives is dictionary[i][j]. –
Don't free() anything allocated on the stack (i.e. buffer).
Also, your function inputString() will not tell its client what memory it had allocated, since p1 is local to it.
Here is an example.
char*** dictionary;
int i = 0;
int j = 0;
int lines = 10;
dictionary = (char***)malloc(sizeof(char**)*lines);
for(i=0;i<lines;i++)
{
dictionary[i] = (char**)malloc(sizeof(char*)*4);
for(j=0;j<4;j++)
dictionary[i][j] = (char*)malloc(sizeof(char)*25);
}
You have to modify the malloc's parameters in order to adapt to your problem/ or modify them when you need more memory for your strings.
Also it might be a good idea to try and free memory when you do not need it
Don't forget to malloc like this...
dictionary[i][j] = (char*)malloc(sizeof(char)*strlen(word_to_insert)+1);
...because each word end with a supplementary byte filled with 0 "null terminate string".
a sample
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
char ***dictionary;
const char *words[] = { "ASEAN", "United Nations", "OPEC" };
size_t howManyWords = sizeof(words)/sizeof(*words);
int i;
dictionary = malloc(howManyWords*sizeof(char**));
printf("Please enter the definition of this word\n");
for(i = 0; i < howManyWords; ++i){
char buff[80];
char **keyValue;
printf("%s : ", words[i]);
fgets(buff, sizeof(buff), stdin);
keyValue = malloc(2*sizeof(char*));
keyValue[0] = (char*)words[i];
keyValue[1] = malloc(strlen(buff)+1);
strcpy(keyValue[1], buff);
dictionary[i] = keyValue;
}
//print
for(i=0;i<howManyWords;++i){
printf("%s : %s", dictionary[i][0], dictionary[i][1]);
}
//release
for(i=0;i<howManyWords;++i){
free(dictionary[i][1]);
free(dictionary[i]);
}
free(dictionary);
return 0;
}

Copying int array to Struct int*

Hi I'm trying to read variables from a file into a int array so I can store them in a Struct array. The numbers get stored correctly into the curLinks array but when I try pass the curLinks array into curNodes.nodes, it doesn't work and when i try print it out (to test) it prints rubbish numbers. Any help would be great.
struct nodeInfo* getTopology(FILE *file){
int totLinks=0;
fscanf(file, "%d", &nodeCount);
struct nodeInfo netTopo[nodeCount];
// How many links does node have
for (int id=0; id<nodeCount; id++){
struct nodeInfo curNode;
curNode.n=id;
fscanf(file, "%d", &totLinks);
int curLinks[totLinks];
for(int i=0; i<totLinks; i++){
int digit=0;
fscanf(file, "%d", &digit);
curLinks[i] = digit;
}
curNode.nodes = curLinks;
netTopo[id] = curNode;
}
for (int id=0; id<nodeCount; id++){
for (int j=0; j<3; j++){
printf("%d ", netTopo[id].nodes[j]);
}
}
return netTopo;
}
You define curLinks multiple time in the first for-loop
int curLinks[totLinks];
And after you fill that you try to set that in your nodeinfo however as soon as the next iteration in the for-loop is entered and curLinks is filled again, the memory of your previous curLinks is out of scope and the memory where you think your read in values should reside can be actually filled with anything - Undefined Behaviour
If you tell me the way you define your structs nodeInfo I might be able to show you how to do it properly.
e.g.: Assuming you define
struct nodeinfo {
int *nodes;
};
Then
struct nodeInfo* getTopology(FILE *file)
{
int id, digit=0, totLinks=0;
fscanf(file, "%d", &nodeCount);
struct nodeInfo netTopo[nodeCount];
// How many links does node have
for (id=0; id<nodeCount; id++){
fscanf(file, "%d", &totLinks);
netTopo[id].nodes = malloc(totLinks * sizeof(int));
if (netTopo[id].nodes==NULL)
printf("Error allocating memory\n");
for(i=0; i<totLinks; i++) {
fscanf(file, "%d", &digit);
netTopo[id].nodes[i] = digit;
}
}
// Free the allocate memory
for (id=0; id<nodeCount; id++){
free(netTopo[id].nodes);
}
return netTopo;
}
I think you should use pointers and "malloc" to allocate memory from the heap in this case.

Resources