updating string array inside a function in C - c

I define a string array in main function, and I want to update it inside another function as follows:
#include <stdio.h>
#define SIZE 15
void read_arrays(char *competitors[SIZE], float points[SIZE], int numOfCompetitors)
{
for (int cntr = 0; cntr < numOfCompetitors; cntr++)
{
printf("Enter the name of competitor %d", cntr+1);
scanf("%s", &*competitors[cntr]);
printf("Enter the point of competitor %d", cntr+1);
scanf("%f", &points[cntr]);
}
}
int main()
{
char *competitors[SIZE];
float points[SIZE];
int numOfCompetitors = 0;
while (numOfCompetitors > 15 || numOfCompetitors < 1)
{
printf("Enter the number of competitors: ");
scanf("%d", &numOfCompetitors);
if (numOfCompetitors > 15) printf("Number of competitors cannot be more than 15!\n");
}
read_arrays(&*competitors[SIZE], &points[SIZE], numOfCompetitors);
printf("%f", points[0]);
}
But I get the following error:
cc homework2.c -o homework2
homework2.c: In function ‘main’:
homework2.c:28:14: warning: passing argument 1 of ‘read_arrays’ from incompatible pointer type [-Wincompatible-pointer-types]
read_arrays(&*competitors[SIZE], &points[SIZE], numOfCompetitors);
^
homework2.c:5:6: note: expected ‘char **’ but argument is of type ‘char *’
void read_arrays(char *competitors[SIZE], float points[SIZE], int numOfCompetitors)
I want to assign the values in array of strings with scanf in a loop. How I can manage to do that?

You can just use the name of the variable when you pass it to the function, you also need to specify the size of the char matrix (~ array of strings).
So this: read_arrays(&*competitors[SIZE], &points[SIZE], numOfCompetitors);
Becomes: read_arrays(competitors, points, numOfCompetitors);
Full code:
#include <stdio.h>
#define SIZE 15
void read_arrays(char competitors[SIZE][30], float points[SIZE], int numOfCompetitors)
{
for (int cntr = 0; cntr < numOfCompetitors; cntr++)
{
printf("Enter the name of competitor %d", cntr+1);
// We read up to 29 characters => no overflow as the size is up to 30
scanf("%29s", competitors[cntr]);
printf("Enter the point of competitor %d", cntr+1);
scanf("%f", &points[cntr]);
}
}
int main()
{
char competitors[SIZE][30];
float points[SIZE];
int numOfCompetitors = 0;
while (numOfCompetitors > 15 || numOfCompetitors < 1)
{
printf("Enter the number of competitors: ");
scanf("%d", &numOfCompetitors);
if (numOfCompetitors > 15) printf("Number of competitors cannot be more than 15!\n");
}
read_arrays(competitors, points, numOfCompetitors);
printf("%s", competitors[0]);
printf("%s", competitors[1]);
printf("%f", points[0]);
}

As an alternative to Daniel Illescas you could just allocate space for each competitor that you input. Just be sure to free them later.
#include <stdio.h>
#define SIZE 15
void read_arrays(char *competitors[SIZE], float points[SIZE], int numOfCompetitors)
{
for (int cntr = 0; cntr < numOfCompetitors; cntr++)
{
competitors[cntr] = (char*)calloc(1, 32);
printf("Enter the name of competitor %d", cntr + 1);
scanf("%s", competitors[cntr]);
printf("Enter the point of competitor %d", cntr + 1);
scanf("%f", &points[cntr]);
}
}
int main()
{
char *competitors[SIZE];
float points[SIZE];
int numOfCompetitors = 0;
while (numOfCompetitors > 15 || numOfCompetitors < 1)
{
printf("Enter the number of competitors: ");
scanf("%d", &numOfCompetitors);
if (numOfCompetitors > 15) printf("Number of competitors cannot be more than 15!\n");
}
read_arrays(competitors, points, numOfCompetitors);
printf("%f", points[0]);
}

Related

How to validation struct value is exist or not using for loop in C language

i want to ask you, here in my code i used case condition for input, but i got a trouble, in my code i want to check is my "NIM" value was inputted to struct or not, if it was inputted, it can't be inputted to struct. Here are my code
#include <stdio.h>
#include <string.h>
struct data {
char nim[10];
};
struct data batas[100];
int a, b, c, d;
int i, j;
char x;
void inputdata()
{
printf("\nInput Data\n");
printf("=======================\n");
printf("NIM : "); scanf("%s", batas[a].nim);
for(i=0; i<a; i++){
if (strcmp(batas[a].nim, batas[i].nim) == 0) {
x = "FLAG";
} else {
x = "FLAGX";
}
}
printf("%s", x);
if (strcmp(x, "FLAGX") == 0) {
a++; // This will input to struct
}
}
void showdata()
{
j=0;
for(i=0; i<a; i++){
j = j + 1;
printf("\nData-%i", j);
printf("\nNIM : %s", batas[i].nim);
}
}
int main() {
int menu;
do {
printf("\n\Choose input = "); scanf("%d", &menu);
switch(menu)
{
case 1 : inputdata(); break;
case 2 : showdata(); break;
}
}while (menu != 3);
return 0;
}
From this i always get an error Segmentation Fault. I appreciate you guys, thank you.
You have already got many suggestion to check your program for warnings and errors.
Check warnings and errors of your program : https://onlinegdb.com/By1VeOK1d
main.c:20:9: warning: assignment makes integer from pointer without a cast [-Wint-conversion]
main.c:22:9: warning: assignment makes integer from pointer without a cast [-Wint-conversion]
main.c:25:12: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
main.c:26:14: warning: passing argument 1 of ‘strcmp’ makes pointer from integer without a cast [-Wint-conversion]
/usr/include/string.h:144:12: note: expected ‘const char *’ but argument is of type ‘char’
main.c:44:12: warning: unknown escape sequence: '\C'
All of the above warnings will be cleared just by making two changes to your code
line 11 change char x; as char* x;
line 44 change printf("\n\Choose input = "); as printf("\n Choose input = ");
Moving on to your code correctness, your function inputdata() is depending on global variable a and the loop for(i=0; i<a; i++){ is never true because i < a will never be true, since a is global (default value 0).
Which leads to execution of other statements in an undefined way.
you are directly reading your input into structure scanf("%s", batas[a].nim);, instead read into a local variable like char temp[30] , then add it your batas and continue checking for the existence of your string from next input.
#include <stdio.h>
#include <string.h>
struct data {
char nim[10];
};
struct data batas[100];
int a, b, c, d;
int i, j, flag;
void inputdata()
{
flag = 0;
printf("\nInput Data\n");
printf("=======================\n");
printf("NIM : ");
scanf("%s", batas[a].nim);
for(i=0; i<a; i++){
if (strcmp(batas[a].nim, batas[i].nim) == 0) {
flag = 1;
}
}
if (flag == 0) {
a++; // This will input to struct
}
}
void showdata()
{
j=0;
for(i=0; i<a; i++){
j = j + 1;
printf("\nData-%i", j);
printf("\nNIM : %s", batas[i].nim);
}
}
int main()
{
int menu;
do {
printf("\n\Choose input = "); scanf("%d", &menu);
switch(menu)
{
case 1 : inputdata(); break;
case 2 : showdata(); break;
}
}while (menu != 3);
return 0;
}

C program, where I should print array of a SECTION in an array

I built a program in C that is printing average of whole array with pointers and function. I need to make the function print a average of user selected section of an array, for example I put these number in an array: 9,8,2,3,6,4 and I want to make a average from just 2-4-. I am stucked, can you help me please? Thanks.
Code:
#include <stdio.h>
int priemer(int *pole,int n);
int main()
{
int a[100],*pole,n,i;
printf("Zadaj pocet prvkov pola (1-100)");
scanf("%d",&n);
while (n > 100 || n < 1)
{
printf("Chyba! Cislo musi byt v rozmedzi od 1 po 100.\n");
printf("Zadaj pocet prvkov znova: ");
scanf("%d", &n);
}
for(i=0;i<n;i++){
printf("Zadaj %d. prvok - ",i+1);
scanf("%d",&a[i]);
}
pole=a;
priemer(pole,n);
return 0;
}
int priemer(int *pole,int n)
{
int i,c=0;
float p;
for(i=0;i<n;i++)
{
c+=*(pole+i);
}
p=(float)c/n;
printf("Priemer vsetkych prvkov v poli je: %.3f\n",p);
return p;
}

Stack around the variable was corrupted with pointer arithmetics

With the code below, I'd always run into "Stack around the variable 'UserCode' was corrupted.
If I'm not mistaken, when I do userCode = (char*)malloc(sizeof(char)*N);, shouldn't it create an "array" with size of char*n ? I'm guessing my issue is either with my declaration of an array, or my pointer arithmetic.
Any help would be highly appreciated.
#include "stdafx.h"
#include <math.h>
int userPrompt1() {
int numOfAlphabets = 0;
printf("Please enter a number from 1 to 8 to choose how many alphabets you want\n");
scanf_s(" %d", &numOfAlphabets);
if (numOfAlphabets > 8 || numOfAlphabets < 0) {
printf("Sorry! Invalid number entered. Try again. \n");
numOfAlphabets = userPrompt1();
}
return numOfAlphabets;
}
int userPrompt2() {
int numOfLetters = 0;
printf("Please enter the number of letters you want to guess\n");
scanf_s(" %d", &numOfLetters);
if (numOfLetters < 0) {
printf("Sorry! Invalid number entered. Try again. \n");
numOfLetters = userPrompt2;
}
return numOfLetters;
}
int tryCalculator(int K, int N) {
int tries = 0;
tries = 1 + ceil(N * log2(K));
return tries;
}
void codeGenerator(char codeGuessIn[], char letters[], int size) {
for (int i = 0; i < size; i++) {
int rando = rand() % size;
codeGuessIn[i] = letters[rando];
printf(" %c", codeGuessIn[i]);
}
printf("\n");
}
void codeChecker(char codeGuessIn[], char generatedCode[], int size) {
int correctAlphabets = 0;
for (int i = 0; i < size; i++) {
if (codeGuessIn[i] == generatedCode[i]) {
correctAlphabets++;
}
}
printf(" %d in correct place \n", correctAlphabets);
}
void getUserCode(int size, char *userCode[]) {
for (int i = 0; i < size; i++) {
printf("Please enter letter #%d \n", i+1);
getchar();
scanf_s(" %c", &userCode[i]);
}
}
int main(void)
{
char letters[8] = { 'A','B','C','D','E','F','G','H' };
char *generatedCode; //array to hold generated code
char *userCode; // array to hold generated code.
int K = userPrompt1(); //how many different alphabets in code
int N = userPrompt2(); //how many letters in code
int tries = tryCalculator(K, N);
//int gameEnd = 1;
userCode = (char*)malloc(sizeof(char)*N);
generatedCode = (char*)malloc(sizeof(char)*N);
codeGenerator(generatedCode, letters, N);
getUserCode(N, &userCode);
//codeChecker(userCode, generatedCode, N);
return 0;
}
void getUserCode(int size, char *userCode[]) {
scanf_s(" %c", &userCode[i]);
Here, userCode[i] is a char * (pointer-to-char), &userCode[i] is a char ** (pointer-to-pointer-to-char), and scanf("%c") expects a char *. A good compiler would warn about that.
I think what you meant to do here is something like:
void getUserCode(int size, char *userCode) {
scanf_s(" %c", &userCode[i]);
}
int main(void) {
char *userCode = malloc(N);
getUserCode(N, userCode);
}
The printf(), getchar(), scanf() combination here reeks of the bad habits created by scanf: you're discarding the first character entered by the user because you're relying on an extra character in the input buffer.
See http://c-faq.com/stdio/scanfprobs.html and read full lines of input with fgets() instead of using scanf().
Also,
int userPrompt2() {
int numOfLetters = 0;
...
numOfLetters = userPrompt2;
}
You're assigning a function pointer to an int. (A normal compiler should warn about this.) If the idea here is to call the function again to repeat the prompt in case the user enters something silly, it's probably a better idea to use a loop instead of a recursive call anyway.

Converting integer to string with atoi/sprintf

This is not my whole code I just sum it up to be easy to see. I have no problem to convert the string into an integer but I cannot convert the integer into a string.
The program just crashes. Here is the code. Look at the line with itoa.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#define SIZEX 49
#define SIZEY 6
int main() {
size_t x, y;
char *a[50][7];
char name[50][100];
char surname[50][100];
char IN[50][100];
char YOB[50][100];
char usname[50][100];
char pass[50][100];
char totamount[50][100];
for (x = 0; x <= SIZEX; x++) {
a[x][0] = name[x];
a[x][1] = surname[x];
a[x][2] = IN[x];
a[x][3] = YOB[x];
a[x][4] = usname[x];
a[x][5] = totamount[x];
a[x][6] = pass[x];
}
printf("\nPlease enter the name of the new user\n");
scanf(" %s", a[0][0]);
printf("Please enter the surname of the new user\n");
scanf(" %s", a[0][1]);
printf("Please enter the Identity Number of the new user\n");
scanf(" %s", a[0][2]);
printf("Please enter the year of birth of the new user\n");
scanf(" %s", a[0][3]);
printf("Please enter the username of the new user\n");
scanf(" %s", a[0][4]);
strcpy(a[0][6], a[0][4]);
strrev(a[0][6]);
a[0][5] = "0";
int z;
z = atoi(a[0][5]);
z = z + strlen(a[0][4]) * 10;
itoa(z, a[0][5], 10);
//sprintf(a[0][5], "%d", z);
printf("%s\n", a[0][5]);
printf("%d\n", z);
return 0;
}
By doing this:
a[0][5]="0";
You are assigning to a[0][5] a pointer to a readonly memory containing string literal "0".
Here:
itoa( z, a[0][5],10 );
you are attempting to write there, giving you memory access violation.

Accessing struct array elements

This program is supposed to capture input from the user into the struct and then print out a histogram of the given information. Everything works fine so far except that when I try to print the histogram all the '*' characters fall under the F grade no matter what the student's grade. What I think is happening is that the student's array index is being passed instead of the actual variable itself, but I'm confused because in the output before the histogram is printed it shows the correct value. Any suggestions?
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 28
#define MAXGRADE 100
struct studentData{
char studentID[MAXSIZE];
char studentName[MAXSIZE];
int examPercent;
} studentRecords[MAXSIZE];
// function prototype for histogram
void displayHist(struct studentData *records, int classSize);
int main()
{
int i, students = -1;
//struct studentData *studentRecords[MAXSIZE];
while(students < 0 || students > MAXSIZE)
{
printf("Please enter the number of students in your class:\n");
scanf("%d", &students);
if(students > MAXSIZE || students <= 0)
{
printf("Try again..\n");
scanf("%d", &students);
}
}
for(i=0;i<students;i++) {
printf("Please enter the student #%d's lastname:\n", i+1);
scanf("%s", &studentRecords[i].studentID);
printf("Please enter the student #%d's ID#:\n", i+1);
scanf("%s", &studentRecords[i].studentName);
printf("Please enter the student's exam percent:\n");
scanf("%d", &studentRecords[i].examPercent);
}
//This is just here to view the input...
for(i=0;i<students;i++) {
printf("Student #%d's name is %s\n", i+1, studentRecords[i].studentName);
printf("student #%d's ID#:%s\n", i+1, studentRecords[i].studentID);
printf("student #%d's grade was %d\n", i+1, studentRecords[i].examPercent);
}
displayHist(&studentRecords[students], students);
return 0;
}
void displayHist(struct studentData *records, int classSize)
{
int i;
printf("A:");
for(i=0;i<classSize;i++)
{
if(records[i].examPercent >=90)
{
printf("*");
}
}
printf("\n");
printf("B:");
for(i=0;i<classSize;i++)
{
if(records[i].examPercent< 90 && records[i].examPercent >= 80)
{
printf("*");
}
}
printf("\n");
printf("C:");
for(i=0;i<classSize;i++)
{
if(records[i].examPercent < 80 && records[i].examPercent >= 70)
{
printf("*");
}
}
printf("\n");
printf("D:");
for(i=0;i<classSize;i++)
{
if(records[i].examPercent< 70 && records[i].examPercent >= 60)
{
printf("*");
}
}
printf("\n");
printf("F:");
for(i=0;i<classSize;i++)
{
if(records[i].examPercent < 60)
{
printf("*");
}
}
}
displayHist(&studentRecords[students], students);
&studentRecords[students] is an address after your array studentRecords. In displayHists, accesses to records[i] will try to dereference studentRecords[students+i], which is outside the bounds of your array.
A correct call could be:
displayHist(&studentRecords[0], students);
Which is equivalent to:
displayHist(studentRecords, students);
By the way, no need to use & in scanf with char *, because char (*)[] and char * may have different memory representations.
scanf("%s", &studentRecords[i].studentID);
scanf("%s", &studentRecords[i].studentName);
warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char (*)[28]’ [-Wformat]
When you use address-of, i.e. &, it becomes char **, which is not what scanf expects.
So try using this way.
scanf("%s", &(*studentRecords[i].studentID));
and
displayHist(studentRecords, students);

Resources