How to access data from an array of strings? C - c

I am having lot of problems with my C code. I am saving data into my array with this function:
/**
* Insert Data into array
* #param char[] pointer
*/
void insertData(char **data) {
int i;
for (i = 0; i < 2; i++) {
data[i] = malloc(10000);
printf("Nombre del paciente %d: ", i+1);
scanf("%s", &data[i][0]);
printf("Habitacion: ");
scanf("%s", &data[i][1]);
printf("Cama: ");
scanf("%s", &data[i][2]);
free(*data);
}
}
My variable data is : char data[2][3];
And I'm trying to show this data with the next function:
void mostrarResultados(char **data) {
int i,j;
for (i = 0; i < 2; i++) {
printf("\n");
for (j = 0; j < 3; j++) {
printf("%c ", data[i,j], **data);
}
}
}
But the console return me weird characters:
What am I doing wrong?
To these functions I am calling them this way:
//First menu
do{
switch (option){
case 1:
insertData(data);
setFirstTime(false);
mostrarResultados(data);
break;
case 2:
exit(0);
break;
}
} while (option == 0);
}
Thank you very much for your help!

I think you better can use a struct to hold the data. Someting like
Struct data {
char nombre[32];
Char habitacion[32];
char cama[32];
}
And malloc the struct malloc(sizeof(struct data) * nr of struct you want)

When programming in C or C++, you must enable compiler warnings, understand them and fix them properly. Everything else is irresponsible.
In this case, the compiler will warn about the printf call, since you are passing the wrong type (and number) of arguments.

Related

C - numbers not entering in the "if condition", dont know why

So, basically, I was instructed to make a function that asks the user for a size, and then creates an array with elements chosen by the user...
for example: size:4 , input:10 20 30 40, created array = {10,20,30,40}.
Then next step the user is to apply some function for this created array. Example:
For example, if the user chooses letter 'A' the function "add1" will be applied and all elements of the array will be increased in one unit, so with an input example of {10,20,30,40}, the output will be {11,21,31,41}.
My code is not working, why? Someone can help me? I've used the debugger and the function is not entering in the "if condition".
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int* add1(int* array, int size)
{
int *novo;
novo = malloc(size*sizeof(int));
for (int i = 0; i < size; i++){
*(novo + (i)) = *(array + i)+1;
}
return novo;
};
int* add2(int* array, int size)
{
int *novo;
novo = malloc(size*sizeof(int));
for (int i = 0; i < size; i++){
*(novo + (i)) = *(array + i)+2;
}
return novo;
};
void print1(int* array, int size)
{
for (int i = 0; i < size; i++)
{
printf("%i\n", *(array+i));
}
};
int main(void)
{ int i, elemento, size;
char *new;
printf("Insert Size:\n");
scanf("%i", &size);
int newArray[size];
printf("Insert Elements:\n");
for (i = 0; i < size; i++)
{
scanf("%i", &elemento);
newArray[i] = elemento;
}
printf("Select option:\n");
scanf(" %c", &new);
if (new == 'A') {
int* result;
result = add1(&newArray, size);
print1(result, size);
} else if (new == 'B') {
int* result;
result = add2(&newArray, size);
print1(result, size);
} else if (new == 'C') {
} else if (new == 'D') {
}
}
Change:
char *new;
to
char new;
as
scanf(" %c", &new);
is expecting a character and as the code stands new is an undefined character pointer. So passing a pointer to a undefined pointer is not good.
PLEASE SWITCH ON YOUR COMPILER WARNINGS AND THIS WOULD BE PICKED UP!
new is not a good variable name. As it leads to confusion with C++ keyword
Check the return values for scanf- see the manual page for that
Perhaps using switch instead of if new == 'A' .....

Having a fatal error code - corrupted heap

New picture from an external compiler.. the exit code is ok?
enter image description here
This is the full code. I'm having a trouble program blows away after printing the wanted output to the screen. I guess it's a problem with the way I allocated memory for the array of structs, and the .name field of each struct in a for loop.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#define MAX_NAME_LEN 50
typedef struct stud
{
char *name;
int marks[4];
float avg;
}student;
student* Create_Class(int);
void Avg_Mark(student*);
void Print_One(student*);
void printExcellent(student*);
void main()
{
int size, i;
student *arr, *newArr;
printf("\nEnter the number of students: ");
scanf_s("%d", &size);
newArr = Create_Class(&size);
for (i = 0; i < size; i++)
{
printExcellent(newArr+i);
}
for (i=0;i<size;i++) free(newArr[i].name);
free(newArr);
_getch();
}
student* Create_Class(int size)
{
student *p;
char str[MAX_NAME_LEN];
int i, j;
p = (student*)calloc(size , sizeof(student));
if (!p)
{
printf("Memory allocation failure.");
exit(1);
}
for (i = 0; i < size; i++)
{
printf("Enter your name: ");
rewind(stdin);
gets(str);
p[i].name = (char*)calloc(strlen(str)+1,sizeof(char));
if (!(p[i].name))
{
printf("Memory allocation error!");
exit(1);
}
strcpy_s(p[i].name,50,str);
printf("Enter your marks: ");
for (j = 0; j < 4; j++)
{
scanf_s("%d", &p[i].marks[j]);
}
Avg_Mark(p + i);
}
return p;
}
void Avg_Mark(student* s)
{
int i, sum=0;
for (i = 0; i < 4; i++)
sum += s->marks[i];
s->avg = (float)sum / 4;
}
void Print_One(student* s)
{
printf("The average of %s is %.1f\n", s->name, s->avg);
}
void printExcellent(student* s)
{
if ((s->avg) > 85)
Print_One(s);
}
Gonna point out everything fishy I see for you:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#define MAX_NAME_LEN 50
typedef struct stud
{
char *name;
int marks[4];
float avg;
}student;
student* Create_Class(int);
void Avg_Mark(student*);
void Print_One(student*);
void printExcellent(student*);
void main()
{
int size, i;
student *arr, *newArr;
printf("\nEnter the number of students: ");
scanf_s("%d", &size);
// This is wrong. Remove the &...
newArr = Create_Class(&size);
for (i = 0; i < size; i++)
{
printExcellent(newArr+i);
}
for (i=0;i<size;i++) free(newArr[i].name);
free(newArr);
_getch();
}
student* Create_Class(int size)
{
student *p;
char str[MAX_NAME_LEN];
int i, j;
// Consider checking size for a sane value.
// Ok, allocate an array of students.
p = (student*)calloc(size , sizeof(student));
if (!p)
{
printf("Memory allocation failure.");
exit(1);
}
for (i = 0; i < size; i++)
{
printf("Enter your name: ");
// These 2 lines scare the heck out of me. I'd really do this differently.
// gets is the devil and the see:
// https://stackoverflow.com/questions/20052657/reversing-stdin-in-c
// for why this may not work well.
rewind(stdin);
gets(str);
// What if str is not a terminated string? Then 1 char of 0? Guess this is ok. Hope it doesn't overflow on the copy below though (consider fixed max size and not using a temporary)
p[i].name = (char*)calloc(strlen(str)+1,sizeof(char));
if (!(p[i].name))
{
printf("Memory allocation error!");
exit(1);
}
// Do a fast copy of up to 50 chars. I'd really want to verify this output to be sure it works.
strcpy_s(p[i].name,50,str);
printf("Enter your marks: ");
for (j = 0; j < 4; j++)
{
// Hope this inputs the way you want.
scanf_s("%d", &p[i].marks[j]);
}
// This should work, but I prefer more explicit pointers.
Avg_Mark(p + i);
}
return p;
}
void Avg_Mark(student* s)
{
// What if s is Null?
int i, sum=0;
// 4 is a magic number. Make this a constant.
for (i = 0; i < 4; i++)
sum += s->marks[i];
// This won't be as accurate as you want. Consider an integer solution.
s->avg = (float)sum / 4;
}
void Print_One(student* s)
{
// What if s is Null? What about s->name?
printf("The average of %s is %.1f\n", s->name, s->avg);
}
void printExcellent(student* s)
{
// What if s is Null?
if ((s->avg) > 85)
Print_One(s);
}
Note: While going through this code, I did not see any "red flags" except for the & on the size and perhaps the gets/rewind calls. I'd still add null asserts to your functions and also walk through it with a debugger to be sure that everything is as you expect. Honestly, there is enough going on here that I'd prefer the debugger help to my quick trace of the code while I was writing comments.
Update
If I change all your scanf_s to scanf() calls, replace your gets() / rewind() calls to a simple scanf("%s", str) call, and change your funky strcpy_s() function to a simpler strcpy() or strncpy() call, your program does not seem to crash for me. My money is that the strcpy_s() call is corrupting RAM while doing its "fast" copy.

Dynamic array of Structs, delet elements

I am trying to create a database program of students where you should be able to add/modify and delete students. I have managed to get the add function working, and also the modify function but the delete function gives me some problems. my code seems to crash when im trying to delete a student from the database, can anyone tell me where the problem lies?
Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* TODO: Avoid global variables. */
struct student {
char name[60];
long long personalNumber;
char gender[6];
char studyProgram[60];
char email[30];
int age;
};
struct student *pointer = NULL;
int numberofstudents = 0;
void modify()
{
long long persnr;
long long comp;
int match = 0;
printf("Please enter the personal number that you wish to modify: \n");
scanf("%lld", &persnr);
getchar();
for(int i = 0; i <= numberofstudents; i++)
{
comp = ((pointer+i)->personalNumber);
printf("%lld\n", ((pointer+i)->personalNumber));
printf("%lld\n", comp);
printf("Inne");
if (pointer[i].personalNumber == persnr && match == 0)
{
printf("Enter name, personalnumber, gender, studyprogram, email and age in this order\n");
scanf("%s%lld%s%s%s%d", (pointer+i)->name, &(pointer+i)->personalNumber, (pointer+i)->gender, (pointer+i)->studyProgram, (pointer+i)->email, &(pointer+i)->age);
match = 1;
getchar();
}
if (match == 0)
{
printf("Could not find person");
}
}
}
void deletestudent()
{
long long persnr;
long long comp;
int match = 0;
printf("Please enter the personal number that you wish to delete: \n");
scanf("%lld", &persnr);
getchar();
struct student *temporary = malloc((numberofstudents - 1) * sizeof(struct student));
for(int i = 0; i <= numberofstudents; i++)
{
if (pointer[i].personalNumber == persnr && match == 0)
{
match = 1;
}
else if (match == 1){
temporary[i-1] = pointer[i];
}
else
{
temporary[i] = pointer[i];
}
if (match == 0)
{
printf("Could not find person");
}
}
free(pointer);
pointer = temporary;
}
void add(){
if (numberofstudents > 0)
{
pointer = (struct student*) realloc(pointer, (numberofstudents+1) * sizeof(struct student));
printf("Lyckades allokeringen!\n\n");
}
printf("Enter name, personalnumber, gender, studyprogram, email and age in this order\n");
scanf("%s%lld%s%s%s%d", (pointer+numberofstudents)->name, &(pointer+numberofstudents)->personalNumber, (pointer+numberofstudents)->gender, (pointer+numberofstudents)->studyProgram, (pointer+numberofstudents)->email, &(pointer+numberofstudents)->age);
getchar();
printf("Visar data:\n");
for(int i = 0; i <= numberofstudents; ++i)
{
printf("%s\t%lld\t%s\t%s\t%s\t%d\n", (pointer+i)->name, (pointer+i)->personalNumber, (pointer+i)->gender, (pointer+i)->studyProgram, (pointer+i)->email, (pointer+i)->age);
}
numberofstudents = numberofstudents+1;
}
int main(void)
{
pointer = (struct student*) malloc(2 * sizeof(struct student));
if (pointer == NULL)
{
printf("pointer NULL");
exit(1);
}
int run = 1;
int choice;
while (run == 1)
{
printf("Please enter an option listed below\n1.ADD\n2.Modify\n3.Delete\n4.Search\n5.Save\n6.Load\n7.Exit");
scanf("%d", &choice);
getchar();
switch(choice) {
case 1 :
add();
break;
case 2 :
modify();
break;
case 3 :
deletestudent();
case 7 :
exit(0);
break;
default :
break;
}
}
return 0;
}
As mentioned in a comment, this:
for(int i = 0; i <= numberofstudents; i++)
is a huge warning sign. In C, such a loop should typically have i < numberofstudents in it, assuming numberofstudents is the actual length of the array.
Using <= rather than < makes the loop go one step too far, thus indexing outside the array and causing undefined behavior.
Writing outside heap-allocated memory and then trying to free() it is a good way to provoke crashes, since there's a chance you're stepping on the heap allocator's data structures (in practice; in theory all that happens is that you get undefined behavior and thus anything can happen).

printing a 2d array of string in c

i'm trying to print a 2d array of string as practice(i'm a newbie) with no success i've tried every combination i could think of still nothing i'm sure i'm doing a silly error somewhere i just can't see it here some of the example:
using a pointer :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define lim 10
#define maxx 25
void print(char *);
int main()
{
int i = 1;
char input[lim][maxx];
char *ps = input;
printf("type the list of %d names or type quit to leave \n", lim);
while (i<lim && gets(input[i]) != NULL && strncmp(input[i], "quit", 4)!=0 ) {
i++;
}
printf("i've counted %d names\n", i);
print("\n");
print(ps);
return 0;
}
void print(char *a)
{
int i=0;
printf("the list of names include : \n");
while(*(a) != '\0') {
printf("%s\n", *(a+i));
i++;
}
}
here's the output:
type a list of %d names or type quit to leave :
bla
bli
blo
quit
i've counted 4 names
the list of names include :
segmentation fault (core duped)
another version of the print function is like this :
void print(char aray[lim][maxx])
{
int i,j;
printf("the list of names include : \n");
for(i = 0; i < lim; i++) {
for(j = 0; j < maxx; j++){
puts(aray[i][j]);
//printf("%s\n", aray[i][j]);
}
}
}
i get the same output, can anyone help me debug this ? and thx in advance
In short, it looks like you need to brush up on your pointers. With your original print function:
void print(char *a)
{
int i=0;
printf("the list of names include : \n");
while(*(a) != '\0') {
printf("%s\n", *(a+i));
i++;
}
}
You are printing the value at a + i every iteration. This might sound like what you want, but what you actually pass to print is a pointer to an array of arrays of char (your compiler should be throwing a warning about incompatible pointer types). That is, the "proper" type of ps is (char *)[]. So in the print function you are only advancing the memory address by sizeof(char) with each iteration, whereas what you actually want is to increment it by sizeof(char) * maxx (the size of your array entries). To implement this change, do the following:
change declaration of print
void print(char (*)[maxx]);
change to proper pointer type
char (*ps)[maxx] = input;
And finally, change print function to something like:
void print(char (*a)[maxx]){
printf("the list of names include : \n");
int i;
for (i = 0; i < lim; i++){
printf("%s\n",*a);
a++;
}
}
You need not use the (a+i) syntax, as just advancing a by one each iteration accomplishes the same thing, and is possibly faster for large i. And of course, as others have mentioned, double check your new line printing, I believe you want printf('\n').
You are adding i as 1 which will not help in case of your two dimensional array as the next element will be at maxx location,so you can do something like this
//here lim and max are defined in your program
void print(char *a){
int i=0;
printf("the list of names include : \n");
while(i<(lim*maxx)){
printf("%s\n",a );
i += maxx;
a = a + maxx;
}
}
and the second variant should be
void print(char aray[lim][maxx])
{
int i,j;
printf("the list of names include : \n");
for(i = 0; i < lim; i++) {
cout<<aray[i]<<"\n";
}
}
You start on index 1 in your 2d array, you should start with index 0
int i=1;
Your print function takes an array of characters and then does a printf string of each character which makes no sense
void print(char *a)
{
int i=0;
printf("the list of names include : \n");
while(*(a)!='\0')
{
printf("%s\n",*(a+i));
i++;
}
}
instead make it look like this
void print(char *a[], int strings)
{
int i = 0;
for (; i < strings; ++i)
{
puts( a[i] );
}
}
and call it with the number of strings you read
print(ps,i);
You would also be better off using fgets() instead of gets(), especially since your strings are max 25 chars so its easy to give a longer string. fgets() lets you specify the max size of the string fgets(input[i],maxx,stdin)
Your other function
void print(char aray[lim][maxx])
{
int i,j;
printf("the list of names include : \n");
for(i = 0; i < lim; i++) {
for(j = 0; j < maxx; j++){
puts(aray[i][j]);
//printf("%s\n", aray[i][j]);
}
}
}
does a similar wrong assumption about the level of indirection
arra[i][j] is one character but puts takes a string argument, so puts( arra[i][j] ); is not correct, you could try fputc( arra[i][j], stdout ) instead since fputc takes one character
fix to
void print(char (*)[maxx]);
int main()
{
int i = 0;//int i = 1;
char input[lim][maxx] = { {'\0'}};
char (*ps)[maxx] = input;
printf("type the list of %d names or type quit to leave \n", lim);
while (i<lim && gets(input[i]) != NULL && strncmp(input[i], "quit", 4)!=0 ) {
i++;
}
printf("i've counted %d names\n", i);
printf("\n");//print("\n");
print(ps);
return 0;
}
void print(char (*a)[maxx])
{
int i=0;
printf("the list of names include : \n");
while(i<lim && a[i][0] != '\0') {
printf("%s\n", a[i]);
i++;
}
}

how can i fix these errors in c?

I keep getting these errors. Im trying to make a mine sweeper like game.
well.c: In function 'main':
well.c:170: warning: passing argument 1 of 'bombCheck' makes pointer from integer without a cast
well.c:170: warning: passing argument 3 of 'bombCheck' makes integer from pointer without a cast
well.c: In function 'fillGameBoard':
well.c:196: error: expected declaration or statement at end of input
#include <stdio.h>
#include <stdlib.h>
#define Rows 5
#define Columns 5
#define Bombs 5
void introduction(void)
{
puts("Welcome to the minefield!");
puts("In this level 2 game, you will win by choosing.");
puts("all of the viable wells and not any of the.");
puts("tool breaker spaces. In both games, there are.");
puts("20 viable spaces and 5 tool breakers!");
puts("Have fun and good luck!");
}
void fillGameBoard(char gameBoard[][Columns])
{
int i, j;
FILE *inputFile;
char gameDataFileName[30];
int yes = 0;
do
{
printf("choose your spot");
printf("\nfield1 field2\n");
scanf(" %s",&gameDataFileName);
if ((inputFile = fopen(gameDataFileName,"r")) == NULL)
{
puts("\nWrong input! Try again!");
puts("check spelling, spacing, etc. make it exact!");
}
else
{
yes = 1;
}
} while (yes == 0);
for (i=0; i<Rows; i++)
{
for (j=0; j<Columns; j++)
{
fscanf(inputFile, " %c", &gameBoard[i][j]);
}
fclose(inputFile);
return;
}
void fillUserBoard(char userBoard[][Columns])
{
int i,j; // counters
for (i=0; i<Rows; i++)
{
for (j=0; j<Columns; j++)
{
userBoard[i][j] = '~';
}
}
return;
}
void displayBoard(char board[][Columns])
{
int i, j;
printf("\n ");
for (i = 1; i <= Rows; i++)
{
printf("%d ",i+5);
}
puts("");
for (i = 0; i <=Rows; i++)
{
printf("__");
}
puts("");
for (i=0; i<Rows; i++)
{
printf("%d|",(i+1));
for (j=0; j<Columns; j++)
{
printf(" %c", board[i][j]);
}
puts("");
}
return;
}
char bombCheck (char board[][Columns], int a, int b)
{
char gameOver;
if (board[a][b] == '*')
{
puts("");
puts(" BOOM");
puts("You hit a mine.");
puts("you are deaded.\n");
puts(" GAME OVER!!\n");
gameOver = 'y';
}
else
{
gameOver = 'n';
}
return gameOver;
}
int main (void)
{
char gameBoard[Columns][Rows];
char userBoard[Columns][Rows];
char done;
char win;
char gameOver;
int count;
int i;
int col;
int row;
introduction();
do
{
done=win='n';
count=0;
fillGameBoard(gameBoard);
fillUserBoard(gameBoard);
displayboard(userBoard);
bombcheck();
do
{
displayBoard(userBoard);
printf("choose your column, numbered 1-5\n");
scanf(" %i", &col);
printf("choose your row, numbered 1-5\n");
scanf(" %i", &row);
done = bombCheck(col, row, gameBoard);
if (done='n')
{
count+1;
if (count==((Columns*Rows)-Bombs))
{
printf("you win!\n");
done='y';
}
else
{
done='n';
userBoard[col][row]=gameBoard[col][row];
}
}
} while (done != 'y');
printf("do you want to play again? y/n \n");
scanf(" %c", win);
}while (win != 'y');
return 0;
}
You're missing a brace in fillGameBoard().
for (i=0; i<Rows; i++)
{
for (j=0; j<Columns; j++)
{
fscanf(inputFile, " %c", &gameBoard[i][j]);
} /* Note closing brace! */
}
fclose(inputFile);
You're passing the arguments to bombCheck() in the wrong order.
/* Declared: char bombCheck (char board[][Columns], int a, int b) */
done = bombCheck(gameBoard, col, row);
What's with the bombcheck() call with no arguments? Note that bombcheck() is different from bombCheck(). The C programming language is case-sensitive.
For future reference, post only the minimal code snippets relevant to your question, instead of an entire program.
Case matters in C. bombcheck is not the same as bombCheck.
Argument order matters. You have declared bombCheck with (board, a, b) but are calling it with (col, row, board).
Taking the address of an array is redundant. The & is not necessary in scanf("%s",gameDataFileName);
scanf with %s is pretty unsafe. Watch what happens if you type in more than 30 characters (perhaps substantially more). Try fgets instead.
You're missing a closing brace in fillGameBoard (probably in the second inner for loop).
Your indenting is inconsistent in some places, particularly where you have left aligned return statements (and some other statements at the end of blocks).
Overall, this is a pretty good beginner program. Keep at it, and you'll get familiar with those compiler errors in no time!
There is a missing closing brace } to end the fillGameBoard function.
The number of opening and closing braces don't add up.
line 170: wrong order of arguments
line 51: missing }

Resources