Issues with fgets and printf..printing a string - c

working on a c project and I've hit a roadblock. I'm trying to print the point coordinate style, and I've included all the code necessary to help you folks help me out!
//point.h
struct Point{
char label;
int x;
int y;
};
//point.c
displayPoint(struct Point p){
char label = p.label;
int x = p.x;
int y = p.y;
// label: (x, y)
printf("(%c: (%d, %d)", label, x, y);
}
//build point from standard input
readPoint(){
struct Point point;
printf("Enter label (character): ");
fgets(buff, MAX_LINE, stdin);
point.label = buff; //I think this is the issue here
printf("Enter x:");
fgets(buff, MAX_LINE, stdin);
point.x = (int) strtol(buff, NULL, MAX_LINE);
printf("Enter y:");
fgets(buff, MAX_LINE, stdin);
point.y = (int) strtol(buff, NULL, MAX_LINE);
Upon compilation, I receive the following error:
points.c: In function 'displayPoint':
points.c: warning: initialization makes pointer from integer without a cast [enabled by default]
points.c: warning: format '%c' expects argument of type 'int', but argument 2 has type 'char *' [-Wformat]
points.c: In function 'readPoint':
points.c: warning: assignment makes integer from pointer without a cast [enabled by default]
If I create a Point using the following information:
Label: A
x: 2
y: 3
and run displayPoint I get this output:
R: (2, 3)
Obviously that's wrong, I don't know where the R came from. What am I missing here? Why does C have to be so stubborn, this would be so simple to do in java, python, etc

You've got a couple of problems here:
fgets gets a buffer, not a single character. I hope buff is declared as a character array (char buff[MAX_LINE]).
Your struct declares a single character for its label, but you're assigning your buffer to the character.
You're reusing the buffer. Because this is just a pointer to a chunk of memory, you're potentially clobbering old data. You might (read, probably will want to) reset your buffer between uses.
Given this, I think what you intend is this:
point.label = buff[0];
I'm guessing you just want a single character for your label, in which case this should work and you won't be clobbering that value. (I don't know about the rest of your input.)

You cannot perform such asignment:
point.label = buff;
buff is an array and label is a character. You may use memcopy but if you need a label in your struct put an array there so that you can store it there. In a character you may store 1 character only.

point.label = buff //I think this is the issue here
Do you see a semi-colon on the end of that line?
Don't C statement end with semi-colons?
Same here:
struct Point{
char label;
int x;
int y;
}
Struct declarations should end with a semi-colon.

Related

How to make strcmp() work in my C program

I am about to make an encryption of a textstring, using another textstring as a "key" for my encryption. It is basically just a reorganization of the ASCII-characters.
The key is given and is structured in a bad way, requiring some extra programming. The ASCII-characters are listed in this key with one charachter for each line, and the corresponding encrypted characters two indexes away.
This is the example of "key.txt":
A g
B 9
C ü
D (
E z
...continuing for all ASCII-characters. An encryption in my program would therfore result in:
"EDABEDA" -> "z(g9z(g"
When I am doing the encryption.
I let the program take in an input-string and I create another string with the encryption-key-characters.
I go through each character in the input string with a for-sling. For each character in the input string, I check if there is a matching character in my encryption-key string. In the encryption key I jump 4 steps at a time since I am going to encrypt and only have to compare A,B,C,D...
I use strcmp() to find a match. And when there is a match, when the character in the input string is the same as in the encryption key, I write the encrypted character to the output string. The encrypted character is placed two indexes ahead of the main character in the key-string.
The warnings occur in the strcmp()
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 3000
void encryption(char *input);
int main()
{
char input[] = "EDABEDA";
encryption(input);
}
void encryption(char *input)
{
int length,i,k;
size_t result;
char dicc[1000];
char output[SIZE];
FILE *f;
f = fopen("key.txt","r");
fseek(f, 0, SEEK_END);
length = ftell(f);
fseek(f, 0, SEEK_SET);
result = fread(dicc, 1, length, f);
int lenDic = strlen(dicc);
int lenInp = strlen(input);
for (i = 0 ; i < lenInp ; i++)
{
for (k = 4 ; k < lenDic ; k = k + 4)
{
if (strcmp(input[i],dicc[k]) == 0)
{
output[i] = dicc[k+2];
printf("%c",output[i]);
}
}
}
fclose(f);
}
I get the below warnings, and the program doesn't work. Anyone who can help me with this strcmp-warning and know how I should rearrange my program in order to meet its requirements?
warning: passing argument 1 of ‘strcmp’ makes pointer from integer without a cast [enabled by default]
if (strcmp(input[i],dicc[k]) == 0)
^
In file included from crypt.c:3:0:
/usr/include/string.h:144:12: note: expected ‘const char *’ but argument is of type ‘char’
extern int strcmp (const char *__s1, const char *__s2)
^
warning: passing argument 2 of ‘strcmp’ makes pointer from integer without a cast [enabled by default]
if (strcmp(input[i],dicc[k]) == 0)
^
In file included from crypt.c:3:0:
/usr/include/string.h:144:12: note: expected ‘const char *’ but argument is of type ‘char’
extern int strcmp (const char *__s1, const char *__s2)
^
Use strcmp() to compare strings, not characters. For your case this
if (input[i] == dicc[k])
should work.
Note that char is just an integer type not a string type, there is no string type in c. And one more thing, write safe code! Check of fopen() succeeded, and if length doesn't exceed 999. Pretty much every thing that can be considered an error.

C warning: passing argument 2 of ‘strcpy’ makes pointer from integer without a cast

EXPLANATION:
simply trying to convert a a char to hexadecimal but i keep getting this error and I'm not sure how to get around this
PROBLEM:
warning: passing argument 1 of ‘strtol’ makes pointer from integer without a cast[cs214111#cs lab3]$ vi lab3.c
CODE:
void print_group(char array[])
{
int num,a;
char ch[10];
printf("here ");
for (a = 0 ; a < 8 ; a++)
{
strcpy(ch,array[3]);
num = strtol(ch,0,16);//------------------THIS IS IT//
printf("%i",num);
}
}
You are passing char where char * is expected, maybe
strcpy(ch, &array[3]);
But from your code it would seem like this, is what you actually need
num = strtol(&array[3], 0, 16);
if strcpy() works in this case, then this will work.

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;

A few c questions: static methods, arrays

I am working on a project in C and have stumbled upon a few questions that I hope you fine folks can help me with! The project is just manipulating coordinate points that the user creates via standard input. I've included the different files and their functions below;
//points.h
struct Point{
int x;
int y;
}
//reads points from stdinput into our points array
int pointReader(struct Point points[]);
///////////////
//points.c
void pointReader(struct Point points[]){
//points[] is originally empty array (filled with NULLS)
struct Point point;
char buffer[10];
printf("X Coordinate:");
fgets(buffer, 10, stdin);
point.x = (int)buffer;
printf("Y Coordinate:");
fgets(buffer, 10, stdin);
point.y = (int)buffer;
append(points, point);
}
static void append(struct Point points[], struct Point point){
int i;
for (i = 0; i < 10; i++){
if (points[i] == NULL){
points[i] = point;
}
Upon compilation, I am receiving the following errors and I'm not too sure why:
points.c:115:10: error: invalid storage class for function 'append'
points.c: In function 'append':
points.c:127:17: error: invalid operands to binary == (have 'struct Point' and 'void *')
Also, can I so easily 'toss' around the points[] array like I am attempting to do?
Thanks for any comments!
The first error is most likely because you haven't declared the function append before you call it. Add a function prototype before you call it. In other words, before the pointReader definition, add the following line:
static void append(struct Point points[], struct Point point);
The second error is because the values in the points array are not pointers, and can therefore not be treated like pointers (like comparing it to NULL). You have to use another method of checking if an entry in the array is used or not. For example using the x and y values of -1 or something similar.
You also have another problem, and that is that you can't convert a string to an integer by just casting. You have to use a function such as strtol for that:
point.x = (int) strtol(buffer, NULL, 10);

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