not sure what's going on in this code - c

I have some C code, and I'm not quite sure what's going on.
#include <stdio.h>
#include <stdlib.h>
#define DIM1 7
#define DIM2 5
#define RES_SIZE 1000
typedef double stackElementT;
typedef struct {
stackElementT *contents;
int maxSize;
int top;
int min2;
} stackT;
void StackInit(stackT *stackP, int maxSize) {
stackElementT *newContents;
newContents = (stackElementT *)malloc(sizeof(stackElementT)*maxSize);
if (newContents == NULL) {
fprintf(stderr, "Not enough memory.\n");
exit(1);
}
stackP->contents = newContents;
stackP->maxSize = maxSize;
stackP->top = -1;
}
void StackDestroy(stackT *stackP) {
free(stackP->contents);
stackP->contents = NULL;
stackP->maxSize = 0;
stackP->top = -1;
}
int StackIsEmpty(stackT *stackP) { return stackP->top < 0; }
int StackIsFull(stackT *stackP) { return stackP->top >= stackP->maxSize-1; }
void StackPush(stackT *stackP, stackElementT element) {
if(StackIsFull(stackP)) {
fprintf(stderr, "Can't push element: stack is full.\n");
exit(1);
}
stackP->contents[++stackP->top] = element;
}
stackElementT StackPop(stackT *stackP) {
if(StackIsEmpty(stackP)) {
fprintf(stderr, "Can't pop element: stack is empty.\n");
exit(1);
}
return stackP->contents[stackP->top--];
}
int shell(char* s1, int arg) {
printf("> ");
scanf("%s %d%*c", &s1, &arg);
return arg;
}
int main() {
char cmds[DIM1][DIM2] = {{"push"}, {"pop"}, {"add"}, {"ifeq"}, {"jump"}, {"print"}, {"dup"}};
char* s1; int arg;
arg = shell(s1, arg);
printf("%s\n", &s1);
}
Input: push 4. It prints J+ instead of "push" but prints 4 normally.
It also gives these warnings on compile:
stack.c: In function ‘shell’:
stack.c:60: warning: format ‘%s’ expects type ‘char *’, but argument 2 has type ‘char **’
stack.c: In function ‘main’:
stack.c:71: warning: format ‘%s’ expects type ‘char *’, but argument 2 has type ‘char **’
stack.c:65: warning: unused variable ‘cmds’
stack.c:69: warning: ‘arg’ is used uninitialized in this function
Can someone please explain?

When you use the %s format specifier, it expect a value which is a pointer to the start of a string. In C, this type is char *.
Taking your main function, your variable s1 is of type char *. Therefore, s1 is a valid parameter to printf, so this line is valid:
printf("%s\n", s1);
Note the absence of an & in front of s1. In your code, you used the &, which takes the address of s1, the result of which will be of type char **. This is the wrong type, so don't use the &.
The thing is, printf can't actually tell what type its arguments are, since it is a variadic function. It simply uses whatever arguments are there, according to the types specified in the format string.
The same thing goes for scanf, but there is a pitfall: you must make sure that enough memory is allocated to account for the user input, else you will experience a buffer overflow with unpredictable results. Aside from this, printf and scanf are perfectly complementary.
Anyhoo, this takes care of the compiler warnings, aside from the unused cmds variable (it's unnecessary in the provided code). Also, there is the part of args - it really should be a variable declared inside of shell, and not passed as a parameter, since its value is not even used inside shell.
Don't know what's up with the rest of the code. It's superfluous considering your main function only calls on shell.

Related

Warnings when passing arguments to a function

So I have a code that works how it has to work, but I am getting the "warning: passing argument 2 of 'outsideBettingHistory' from incompatible pointer type", why is that?
My project is huge so I will only rewrite parts that play the role in the warning, so you can paste it yourself and get the same errors.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct Bet {
char* bets[3][2];
} Bet;
void outsideBettingHistory(int x, char betChosen[0][10], bool won, int result) {
//You can ignore what is inside this function
FILE *f;
f = fopen("bettingHistory.txt", "a");
if(!f) {
printf("\nThe bettingHistory.txt not found or unable to open");
exit(0);
}
if(won) {
fprintf(f, "%s %s", "Bet type: ", betChosen[0]);
fprintf(f, ". Won %d credits\n", result);
}
if(!won) {
fprintf(f, "%s %s", "Bet type: ", betChosen[0]);
fprintf(f, ". Lost %d credits\n", result);
}
fclose(f);
}
int betColours(int balance, Bet* betTypes) {
//A lot of stuff that have nothing to do with the warning
int typeOfBet = 0; //This is the example of 3 variables that this function would give to the outsideBettingHistory(); function
bool won = false;
int resultAmount = 8;
outsideBettingHistory(typeOfBet, betTypes->bets[0][typeOfBet], won, resultAmount);
return balance;
}
int main() {
int balance = 100;
Bet betTypes = { .bets={{"Red", "Black"}, {"Even", "Odd"}, {"1 to 18", "19 to 36"}}};
betColours(balance, &betTypes);
}
Also, for void outsideBettingHistory(int x, char betChosen[0][10], bool won, int result) I am getting "note: expected 'char (*)[10]' but argument is of type 'char *'" How do I get rid of these warnings?
In this call
outsideBettingHistory(typeOfBet, betTypes->bets[0][typeOfBet], won, resultAmount);
the second argument has the type char * because the data member bets is a two-dimensional array of pointers of the type char * and you selected the element of the array bets[0][typeOfBet] that is the same as bets[0][0] because typeOfBet was initialized by 0. That is you passed to the function a pointer to the first character of the string literal "Red".
But the second parameter of the function outsideBettingHistory
void outsideBettingHistory(int x, char betChosen[0][10], bool won, int result) {
has the type char ( * )[10].
And the types are not compatible. So the compiler issues an error.
You should decide for yourself what you are trying to pass to the function and what the function shall do.
If it is supposed that the function outsideBettingHistory must deal with a string literal (an element of the two-dimensional array) then declare the function like
void outsideBettingHistory(int x, const char *betChosen, bool won, int result) {

C Pointer Error

The program below is supposed to read a txt file and put the data in a struct. But it gives an pointer error. It gives an error in strcpy() about pointers. I'm new in C. Whats wrong?
#include <stdio.h>
#include <string.h>
int main()
{
struct citydata {
char city[20];
int temp;
};
struct citydata values[15];
struct citydata Avg;
struct citydata high;
struct citydata low;
FILE* inp;
int reccount = 0;
int x = 0;
char s;
int n;
inp = fopen("mydata.txt", "r");
if (!inp) {
printf("Unable ot open file\n");
}
while (fscanf(inp, "%s %d", s, &n) != EOF) {
strcpy(values[x].city, s);
values[x].temp = n;
x++;
}
fclose(inp);
}
Don't ignore compiler warnings.
When if you compile this code (say, with gcc), you get the following warnings:
test.c:27:24: warning: format ‘%s’ expects argument of type ‘char *’, but argument 3 has type ‘int’ [-Wformat=]
while (fscanf(inp, "%s %d", s, &n) != EOF) {
^
test.c:28:32: warning: passing argument 2 of ‘strcpy’ makes pointer from integer without a cast [-Wint-conversion]
strcpy(values[x].city, s);
^
In file included from test.c:2:0:
/usr/include/string.h:125:14: note: expected ‘const char * restrict’ but argument is of type ‘char’
extern char *strcpy (char *__restrict __dest, const char *__restrict __src)
so, as comments suggest, you can't scan directly into the struct; you can only scan into simpler types the C standard libraries recognizes: integer, floating-point numbers, char * strings etc. Similarly, you can't perform a string copy from your structs, which are not strings.
C is a strongly-typed language with very few allowed implicit conversions. In some cases, you are able to pass integers instead of floats or vice-versa, but nothing "magically converts" into a string, or is "magically parsed" from a string.
... and there are other issues:
Note #EdHeal 's comment: If your fopen() fails, you mustn't continue running the rest of the code. Either you should exit(EXIT_FAILURE); or wrap the rest of the code in main() within an else() block.
You should printf error messages to the standard error stream, so instead of printf("error message here") it should fprintf(stderr,"error message here"). Also, the standard C library places an error code you can get as the errno variable, or you can have an error message printed to the standard error stream with the perror() function. There are a few other related related functions (like strerror(), `err() etc.) which I will not get into here.
make some mistakes with pointers=)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct citydata
{
char *city;
int temp;
} citydata;
int main()
{
char *s;
citydata *values;
values = (citydata*)malloc(sizeof(citydata) * 16);
FILE * inp;
int reccount = 0;
int x = 0;
int n;
inp = fopen("mydata.txt", "r");
if(!inp)
printf("Unable ot open file\n");
while (fscanf(inp,"%s %d",s, &n) != EOF)
{
values[x].city = (char*)malloc(sizeof(char) * 20);
strcpy(values[x].city, s);
values[x].temp = n;
x++;
}
fclose(inp);
}

Arrays and Structs

I am taking an online college course introducing C and am completely stumped on my latest project. My professor to research online for the errors but the examples don't seem to match. I started the program on Visual Studio 2013 and now have moved to Code::blocks from the professor's instruction.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
typedef struct flightRec { // declare a struct to match the format of the binary data
char FlightNum[7];
char OriginAirportCode[5];
char DestAirportCode[5];
int timestamp;
} flightRec;
int flightCmp(const void *a, const void *b) // comparison function of DestAirportCode to ascending order
{
const flightRec *p1 = (flightRec *)a;
const flightRec *p2 = (flightRec *)b;
if (p1->DestAirportCode < p2->DestAirportCode)
return -1;
else if (p1->DestAirportCode > p2->DestAirportCode)
return +1;
else
return 0;
}
int codeInst(int count, int i, char currCode, char nextCode, flightRec flightInfo[1000]) { // function that counts how many instances of each code exist
count = 0; // set count to zero
i = 0;
currCode = flightInfo[i].DestAirportCode; // get a code from the array, call it currCode
while (i < 1000 ) { // while you've not come to the end of the array
nextCode = (&flightInfo[i+1].DestAirportCode); // get the next code from the array
if (nextCode == currCode) { // if the next code equals the current code
count += 1; // then add one to count
}
else {
printf("Destination Airport Code: %s Count: %i", flightInfo->DestAirportCode, count); // else output code and count
currCode = nextCode; // set currCode to nextCode
count = 0; // set count to 0
}
++i;
}
}
int main(){
flightRec flightInfo[1000];
int i = 0;
int codeInst;
FILE* inFile = NULL;
inFile = fopen("acars.bin", "rb");
struct tm* timestamp;
if (inFile == NULL) {
printf("Could not open file acars.bin.\n");
return -1;
}
while (!feof(inFile)) {
for (i = 0; i < 1000; ++i) {
fread(&flightInfo[i], sizeof(flightInfo), 1, inFile); // read the acars.bin file into an array of these structs
}
for (i = 0; i < 1000; ++i) {
qsort(flightInfo, 1000, sizeof flightInfo, flightCmp); // sort the array
}
for (i = 0; i < 1000; ++i) {
localtime(flightInfo[i].timestamp); // Do localtime () on the timestamp member of the struct, then asctime on the time struct you get back from localtime
return timestamp;
}
int codeInst(flightInfo); // algorithm to count how many instances of each code exists
for (i = 0; i < 1000; ++i) {
printf("Flight Number: %s \nOriginal Airport: %s \nDestination Airport: %s \nDestination Airport Count:%i \nTime: %d \n\n", &flightInfo[i].FlightNum, &flightInfo[i].OriginAirportCode, &flightInfo[i].DestAirportCode, codeInst, timestamp); // print the flightRec structs in form of member columns
}
}
fclose(inFile);
system("pause");
}
Build Messages:
||=== Build: Debug in Project6 (compiler: GNU GCC Compiler) ===|
In function 'codeInst':|
|28|warning: assignment makes integer from pointer without a cast [enabled by default]|
|30|warning: assignment makes integer from pointer without a cast [enabled by default]|
||In function 'main':|
|70|warning: passing argument 1 of 'localtime' makes pointer from integer without a cast [enabled by default]|
|121|note: expected 'const time_t *' but argument is of type 'int'|
|71|warning: return makes integer from pointer without a cast [enabled by default]|
|74|error: expected declaration specifiers or '...' before 'flightInfo'|
|76|warning: format '%s' expects argument of type 'char *', but argument 2 has type 'char (*)[7]' [-Wformat]|
|76|warning: format '%s' expects argument of type 'char *', but argument 3 has type 'char (*)[5]' [-Wformat]|
|76|warning: format '%s' expects argument of type 'char *', but argument 4 has type 'char (*)[5]' [-Wformat]|
|76|warning: format '%d' expects argument of type 'int', but argument 6 has type 'struct tm *' [-Wformat]|
83|warning: control reaches end of non-void function [-Wreturn-type]|
c||In function 'codeInst':|
|43|warning: control reaches end of non-void function [-Wreturn-type]|
||=== Build failed: 1 error(s), 10 warning(s) (0 minute(s), 0 second(s)) ===|
You have initially a function called codeInst, after that, in your main function, you declared a integer variable called codeInst, in line 73 you coded a statement that I really don't know what you want to do (int codeInst(flightInfo);).I assume that you want to call the function int codeInst and for that you must:
change the name of the variable like codeInstVarible
assign to codeInstVarible the function codeInstVarible = codeInst()
and fill all existing parameters in the function in case: (int count, int i, char currCode, char nextCode, flightRec flightInfo[1000])
Check out for info:
[c function localtime()][1]
For the error: |121|note: expected 'const time_t *' but argument is of type 'int'|
In your localtime(flightInfo[i].timestamp),
flightInfo[i].timestamp is an int, not a const time_t *(a pointer to a time_t).
For your int codeInst(flightInfo); function, it should have a return type.
In your main function, you wrote
int codeInst(flightInfo);
Which is incorrect. Look at BarbarianSpock's response.

Why are my pointer assignments causing program to crash

I have written the code below as a small program to test out before writing a larger program based on the same basic principle. I had it working yesterday, but it's getting hung up this morning, and I can't figure out why.
The code is getting hung up at: new_rec->next = head;
Please have a look at the code below, and thanks for your help.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
FILE *fptr;
struct list {
char string[256];
char *ptr;
struct list *next;
};
unsigned int breakRemove(char string1[]);
int main(void)
{
if ((fptr = fopen("C:\\Users\\mgreene\\Documents\\EmailTemplates\\TestList.txt", "w")) == NULL)
{
fprintf(stderr, "Error opening file.");
exit(1);
}
int i, j, k, count=0;
char ans[256];
char *pAns;
pAns = ans;
struct list *ptr = NULL;
do
{
puts("\nEnter some text: ");
fgets(ans, 256, stdin);
breakRemove(ans);
if (pAns != '\0');
{
count++;
printf("\n%d. You typed:\"%s\"", count, pAns); //test for correct pAns pointer assignment
}
struct list list1;
struct list *head = NULL;
struct list *new_rec = NULL;
struct list *curr_rec = NULL;
struct list *next_rec = NULL;
new_rec = (struct list*)malloc(sizeof(struct list));
if (!new_rec)
{
puts("\nMemory Allocation Error");
exit(1);
}
puts("\nFirst Memory Allocation Successful."); //acknowledge successful memory allocation
ptr = pAns;
printf("\nptr = %s", ptr); //test for pointer assignment
printf("\npAns = %s", pAns); //test for pointer assignment
head = ptr;
printf("\nhead = %s", head);// test for pointer assignment
printf("\nProblem is new_rec->next=head."); //test to isolate problem.
new_rec->next = head;
printf("\nnew_rec->next = ", new_rec->next);
head = new_rec;
curr_rec = head;
while (curr_rec->next != NULL)
{
curr_rec = curr_rec->next;
}
puts("\nList Pointer Memory Allocation Successful.");
curr_rec->next = new_rec;
new_rec->next = NULL;
strcpy(new_rec->string, ans);
printf("\n%s", curr_rec->string);
if (list1.string != '\0')
{
fprintf(fptr, "\n%d. %s", count, curr_rec->string);
}
}while (*pAns != '\0');
}
unsigned int breakRemove(char string1[]) //Function for removing line breaks from fgets.
{
unsigned int lenString;
lenString = strlen(string1);
if (string1[lenString-1]=='\n')
{
string1[lenString-1]='\0';
}
return (unsigned char)string1;
}
Enable the warnings in your compiler. I got:
../main.c:53:9: warning: assignment from incompatible pointer type [enabled by default]
../main.c:54:5: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘struct list *’ [-Wformat]
../main.c:57:5: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘struct list *’ [-Wformat]
../main.c:62:5: warning: too many arguments for format [-Wformat-extra-args]
../main.c:44:18: warning: unused variable ‘next_rec’ [-Wunused-variable]
../main.c:23:13: warning: unused variable ‘k’ [-Wunused-variable]
../main.c:23:10: warning: unused variable ‘j’ [-Wunused-variable]
../main.c:23:7: warning: unused variable ‘i’ [-Wunused-variable]
../main.c: In function ‘breakRemove’:
../main.c:93:10: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
Fix them for a good start. :)
For example, the first warning is coming from
ptr = pAns;
and then this will be head. That's why your program crashes (one of the reasons probably).
You have
char *pAns;
struct list *ptr = NULL;
and then you assign the one to the other. This doesn't make sense. You should try/study harder, since the errors are many for an answer to fix them.
Another example is here:
if (pAns != '\0')
; <-- suspicious semicolon, remove it
{
count++;
printf("\n%d. You typed:\"%s\"", count, pAns); //test for correct pAns pointer assignment
}
To turn the warnings on in code blocks, you could do this:
"check the option "Enable all compiler warnings" in the settings=>configure plugins=>compiler"
or do this:
that I found here.

Function to decrypt file in C?

I have a file with a large number of 'prospects', so each line has an encrypted last name, an encrypted first name, a 12 digit id code, and then 4 ratings (3 ints, 1 float). Encryption is shifting every character of the names by the value of the last number in the file (found to be 310).
Attempted to create a function to decrypt 1 character, then another function to decrypt a string (name) using this function, but am getting errors and segmentation faults, please help!
#include <stdio.h>
#include <stdlib.h>
#define MSTRLEN 20
#define MAX_SIZE 1000
/* structure prototype */
typedef struct {
char lastname[MSTRLEN];
char firstname[MSTRLEN];
char secretcode[13];
int rank1;
int rank2;
float rank3;
int rank4;
} prospect_t;
int main (void)
{
FILE *ifile;
prospect_t *prospects;
char last[MSTRLEN],first[MSTRLEN],code[13],last_name,first_name;
int r1,r2,r4,num_prospects,shift,i,j;
float r3;
char unencrypt_letter(char *letter, int shift);
char unencrypt_name(char name[MSTRLEN], int shift);
/*finding how many prospects and last integer*/
ifile = fopen("prospects.txt","r");
num_prospects = 0;
if (ifile == NULL){
printf("File not found!\n");
return (-1);
}
while (fscanf(ifile,"%s %s %s %d %d %f %d",last,first,code,&r1,&r2,&r3,&r4)!=EOF){
num_prospects++;
}
shift = r4%26;
fclose(ifile);
/*--------------------------------------*/
/* dynamic memory allocation */
prospects = (prospect_t*)malloc(num_prospects*sizeof(prospect_t));
ifile = fopen("prospects.txt","r");
if (ifile == NULL){
printf("File not found!\n");
return (-1);
}
for(i=0;i<num_prospects;i++){
fscanf(ifile,"%s %s %s %d %d %f %d", prospects[i].lastname,prospects[i].firstname,prospects[i].secretcode,&prospects[i].rank1,&prospects[i].rank2,&prospects[i].rank3,&prospects[i].rank4);
}
/* to be used once get working
for(j=0;j<num_prospects;j++){
prospects[j].lastname = unencrypt_name(prospects[j].lastname,shift);
prospects[j].firstname = unencrypt_name(prospects[j].firstname,shift);
}
*/
/* to be taken out once working */
last_name = unencrypt_name(prospects[0].lastname,shift);
first_name = unencrypt_name(prospects[0].firstname,shift);
printf("%s %s\n",last_name,first_name);
fclose(ifile);
free(prospects);
return(0);
}
/* function to unencrypt one letter */
char unencrypt_letter(char *letter, int shift)
{
char *new_letter;
if ((*letter - shift) < 'a')
*new_letter = (char)((*letter - shift) + 26);
else
*new_letter = (char)(*letter - shift);
return(*new_letter);
}
/* function to unencrypt a name */
char unencrypt_name(char name[MSTRLEN],int shift)
{
char new_name[MSTRLEN];
int k;
k = 0;
while (name[k] != '\0'){
new_name[k] = unencrypt_letter(name[k],shift);
k++;
}
return(*new_name);
}
From terminal, I am getting the following:
la2.c: In function ‘main’:
la2.c:68:2: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat]
la2.c:68:2: warning: format ‘%s’ expects argument of type ‘char *’, but argument 3 has type ‘int’ [-Wformat]
la2.c: In function ‘unencrypt_name’:
la2.c:99:3: warning: passing argument 1 of ‘unencrypt_letter’ makes pointer from integer without a cast [enabled by default]
la2.c:79:6: note: expected ‘char *’ but argument is of type ‘char’
** Link phase
gcc -o la2 la2.o
Compile and link completed successfully
Your binary can be run by typing:
la2
engs20-1:~/engs20/workspace$ la2
Segmentation fault
Read the warnings again, they are quite clear:
la2.c:68:2: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’
It tells you that the second argument to the printf call on line 68 is expected to be a string (char *) but you pass an integer (actually a single char, but the compiler casts it to int) as that argument instead.
Later when you run the program printf uses that integer as a pointer to a string, and as that integer is not a proper integer the program crashes.
Assuming the 2nd fscanf is line 68
fscanf(ifile,"%s %s %s %d %d %f %d", prospects[i].lastname,prospects[i].firstname,prospects[i].secretcode,&prospects[i].rank1,&prospects[i].rank2,&prospects[i].rank3,&prospects[i].rank4);
I'd stick some () in to make sure you are getting the address of what you think.
&(prospects[i].lastname), ...
You don't pre declare char unencrypt_letter(char *letter, int shift) before you call it, so the compiler assumes it returns an int.
Add a predeclaration of it before main().

Resources