Removing a warning after passing array by parameter (C language) - c

The following code passes an array as a parameter from a process of main (called process) into another process (called subprocess). It simulates behavior I want to achieve in code of my own: subprocess fills a string array with the correct strings and then returns them to process for... processing.
#include <stdio.h>
#include <string.h>
void preprocess(char input[10][10]) {
int i;
char temp[10];
for (i = 0; i < 10; i++) {
scanf("%s", &temp);
strcpy(input[i], temp);
}
}
void process() {
int i;
char strings[10][10];
preprocess(strings);
for (i = 0; i < 10; i++) {
printf("%s\n", strings[i]);
}
}
int main() {
process();
return 0;
}
My question: this code generates a warning and I'm not 100% sure about it. Can someone help me remove the warning and clear this code of booby traps?
EDIT: The warning was:
warning: format '%s' expects argument of type 'char *', but argument 2 has type 'char (*)[10]'

The parameter you pass in to scanf is incorrect. The %s format specifier expects a pointer to the first element of an array of char. What you're passing in is the address of the array.
Remove the address-of operator & from the scanf call. When an array is passed to a function, it decays to a pointer to the first element.
scanf("%9s", temp);
The number in the format specifier gives the maximum number of characters to be read. This prevent a potential buffer overflow of temp.

You should use:
scanf("%s", temp);
not
scanf("%s", &temp);

Related

Its saying segmentation fault when i call in the `inputmatrix` function. I made sure the array of pointers pointed to a valid memory space

Im getting an error when i input the first matrix using the inputmatrix function. Am i passing the arguments incorrectly ?
#include <stdio.h>
void inputmatrix(int *a[10],int m,int n)
{
int i,j;
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
{
scanf("%d",(*(a+i) + j));
}
}
}
void multiplymatrix(int *a[10],int *b[10],int *c[10],int m1,int n2)
{
int i,j,k,sum=0;
for(i=0;i<m1;i++)
{
for(j=0;j<n2;j++)
{
for(k=0;k<n2;k++)
sum += *(*(a+i)+k) * *(*(b+k)+i);
}
*(*(c+i)+j)=sum;
}
}
void outputmatrix(int *c[10],int m1,int n2)
{
int i,j;
for(i=0;i<m1;i++)
{
for(j=0;j<n2;j++)
{
printf("%d ",(*(c+i) + j));
}
}
printf("\n");
}
int main()
{
int a[10][10],b[10][10],c[10][10],m1,m2,n1,n2;
printf("Enter the order of the first matrix : ");
scanf("%d%d",&m1,&n1);
printf("Enter the order of the second matrix : ");
scanf("%d%d",&m2,&n2);
if(n1==n2)
{
printf("Enter the first matrix : ");
inputmatrix(a,m1,n1);
printf("Enter the second matrix : ");
inputmatrix(b,m2,n2);
multiplymatrix(a,b,c,m1,n2);
outputmatrix(c,m1,n2);
}
}
You declared the parameter a to your inputmatrix function as an array of 10 pointers to int – but you have not assigned any pointer values to it. As a result you're using random, unknown values of pointers, pointing anywhere, thus you triggered Undefined Behavior.
You're lucky the pointer you use apparently points to a not accessible area of memory, hence a Segmentation Violation. Otherwise your program could pretend it works correctly, and then spectacularly crash somewhere else...
EDIT
The actual error, however, is not missing the pointer initialization but rather ignoring the compiler's warning about passing an argument of incompatible type and, consequently, forcing a program to interpret as pointers data which were not pointers. I have tested the call line in the online GDB compiler at https://www.onlinegdb.com/ and it said:
main.c:12:6: note: expected ‘int **’ but argument is of type ‘int (*)[10]’
The a variable in main() is an array 10 by 10, which is 100 int values stored in a contiguous block of memory. OTOH inputmatrix expects an array of 10 pointers, each pointing somewhere else to an int (or a block of int values).
The actual type of parameter passed to the function is not 'a 10-elements array of pointers to int', as you declared by int *a[10], but rather 'a pointer to a 10-elements array of integers', which should be declared as int (*a)[10].

why this program in way of scanning elements for array in c stops in the third line and don't execute next lines?

#include <stdio.h>
#include <stdlib.h>
int main()
{
int a[3][4];
for (int i=0;i<3;i++){
for(int j=0;j<4;j++){
printf("a[%d][%d]:",i+1,j+1);
scanf("%d",a[i][j]);
}
}
return 0;
}
The program stops in the third line and doesn't execute the next lines
Did you see the compiler warning in your scanf function:
warning: format ‘%d’ expects argument of type ‘int *’, but argument 2 has type ‘int’
So, using
scanf("%d",&a[i][j]);
instead of
scanf("%d",a[i][j]);
This happens because scanf receives an address (pointer) to variable, and not the variable itself. adding & before variable name will refer to it's address

How can I allow a user to input values for an array with a specified initial size?

I want to be able to ask a user of this code for four values for an array. I have some code, but it prints an error that I cannot seem to get around. I'm trying to model some of my code after the example in this video tutorial: https://youtu.be/IPYA3b3_nyk?list=PL6gx4Cwl9DGAKIXv8Yr6nhGJ9Vlcjyymq , however, I cannot seem to get it to compile without errors.
The error goes as follows:
In function ‘main’:
intitializeint.c:12:9: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘int *’ [-Wformat=]
printf("Enter value %d. \n", &i+`);
^
I've tried using printf() and scanf() for each prompt for a value but discovered that this tutorial and tried to mimic it. I've tried rearranging the "&i+1" but it just shoots the same error back. I want to have an increment so that in the output, it shows as if the array started at 1.
#include <stdio.h>
#include <stddef.h>
void printArray(int n[]);
int main(void)
{
int i;
int n[4];
for (i = 0; i < 5; ++i) {
printf("Enter value %d. \n", &i+1);
scanf("%d", &n[i]);
}
printf("%s%13s\n", "Element", "Value");
printArray(n);
return 0;
}
void printArray(int n[])
{
int i;
for (size_t i = 0; i < 4; ++i) {
printf("%7zu%13d\n", i, n[i]);
}
}
When you wrote &i you accidentally created a pointer to i. Your pointer will have type int *, because it is a pointer to an int. The %d format specifier expects an int, not a pointer to an int, so that is why the compiler is giving you that error. (You should re-reread that error and make sure every word of it makes complete sense to you now.)
The solution is to remove the erroneous & operator:
printf("Enter value %d.\n", i + 1);

Scanf Seg Fault

I'm working on my assignment for my C course, and I'm trying to take in the user's input and store it in a variable to use for later in my code. Here's what my main function looks like,
int main() {
// Variables here
char* inputLine[10];
do {
printf("Insert number....");
scanf("%s\n", inputLine);
// More stuff here
}
return 0;
}
This code gives me a bunch of warnings, warning: format specifies type 'char *' but the argument has type 'char **' [-Wformat], and if I change the variable declaration to,
char* inputLine = NULL;
When I execute my code I get a seg fault, can someone explain to me what I am doing wrong, and the differences of what happens in the memory when I'm initializing this variable?
char* inputLine[10];
--> is an array of ten pointers to char
printf's format %s expects argument of type char *, but you're providing it as type char **
Just use
char inputLine[10];
To avoid possible buffer overflow you should use
scanf("%9s", inputLine); //Notice the size with %s
9 only because C string are null terminated ('\0') so one extra byte for it goes at end
char inputLine[10];
do {
printf("Insert number....");
scanf("%9s\n", inputLine);
// More stuff here
} while( //some condition);
However if you edit your code and remove * you get answer, but normal array deprecated, nowdays, programmers use vector, normal array in C not safe :
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<string> inputLine;
You can define with every data type:
vector<int> myvar;
Or you can define multidimensional vector:
vector< vector <int> > myvar;

Modifying an array from another function in C

Here is my main function:
main(){
int *seats[50] = {0};
char x;
do{
printf("A-Add Reservation\tC-Cancel Reservation\n");
scanf("%c", &x);
} while(x != 'a' && x != 'c');
switch(x){
case 'a':
addRes(&seats);
break;
default:
break;
}
}
I am trying to pass seats[] into the addRes() function so I can modify it within addRes(). Here is the function:
void addRes(int **seats[]){
int s, i, scount=0, j=0, k=0, yourseats[]={0};
printf("How many seats do you require? ");
scanf("%i\n", &s);
for(i=0;i<=sizeof(*seats);i++){
if(*seats[i] == 0)
scount++;
}
if(scount >= s){
for(i=0;i<=s;){
if(*seats[i] == 0){
yourseats[j]=i;
*seats[i]=1;
i++; j++;
}
else i++;
}
printf("Your seat numbers are: \n");
while(k < j){
printf("%i\n", yourseats[k]);
k++;
}
}
else {
printf("Sorry, there are not enough seats available.\n");
}
}
It compiles with the warnings:
Line 15 (*seats[i]=1;) Assignment makes pointer from integer without a cast.
Line 53: (addRes(&seats);) Passing argument 1 of 'addRes' from incompatible pointer type.
Line 3: (void addRes(int ** seats[]){) Expected 'int ***' but argument is of type 'int *(*)[50]'.
On running the program it gets to
How many seats do you require?
and does nothing after entering a value.
Any help would be much appreciated!
Declaration int **seats[] in function parameter is == int ***seats, and this means type of *seats[i] is int* and you are assigning a number to it, that is incompatible type error:
*seats[i] = 1;
^ ^ int
|
int*
incompatible types
Next in addRes(&seats);
seats in array of pointer its type if int*[50] that &seat is pointer of array and type of &seat is int*(*)[50] Where as function argument type is int ***, so again type incompatible error.
Notice you are also getting a reasonable error message from compiler: Expected 'int ***' but argument is of type 'int * (*)[50]'.
Suggestion:
As I can see in your code, you don't allocate memory for seats[i] in your function addRes() and So as I understand you not need to declare seat[] array as array of pointers but you need simple array of int.
Change declaration in main():
int *seats[50] = {0};
should be just:
int seats[50] = {0};
// removed * before seats
Next just pass seats[] array's name to addRes() function where declaration of function should be
addRes(int* seats)
or addRes(int seats[])
it make your work pretty simple in function addRes() you can access its elements as seats[i] ( and it no need to use extra * operator).
Length of array:
One more conceptional problem in your code that you are using sizeof(*seats) to know the length of array. Its wrong! because in addRes() function seats is not more an array but a pointer so it will give you the size of address ( but not array length).
And yes to inform about size of seats[] in addRes() function send an extra parameter called length, so finally declare addRes() as follows (read comments):
void addRes(int seats[], int length){
// access seat as
// seat[i] = 10;
// where i < length
}
Call this function from main() as follows:
addRes(seats, 50);
// no need to use &
One more problem that presently you are not facing but you will encounter soon as you will run you code that scanf() need extra enter in function addRes(). To resolve it change: scanf("%i\n", &s); as scanf("%i", &s); no need of extra \n in format string in scanf().
int *seats[50] = {0};
This is an array of integer pointers, all you need is an actual array so drop the * resulting in int seats[50] = {0};.
Also your function signature for an array is wrong, void addRes(int seats[]) will do fine.
Finally, to pass an array to that new signature, you can pass the array directly without any unary address-of operators (arrays will decay to a pointer when passed as an argument to a function):
addRes(seats);
Also as pointed out, when assigning to an array element, you need to drop the *:
seats[i]=1;
Is more than enough. Same goes for the if statements and the like where you do a comparison against an array element.
Regarding your addRes function:
for(i=0;i<=sizeof(*seats);i++)
You will only get the size of the pointer this way, which on a 32bit machine is 4. This trick will not work on an array passed to a function. You will need to pass the array separately.
You can fix it in the following way:
Change the function signature of address to this:
void addRes(int seats[], int size)
Pass the size in one of the following ways in main:
Directly: addRes(seats, 50);
Indirectly: addRes(seats, sizeof(seats)/sizeof(int));
Note that the above only works on local to the scope of this function arrays, it won't work on an array you've obtained as an argument to a function (or dynamically allocated arrays).
Another issue is to do with scanf, you should drop the \n. Use scanf("%i", &s);

Resources