-1

So I write a program to compare stdin txt file and argv and similarities printf, Now my program can only read stdin(not use fopen, and malloc because it prohibited by project rules), if anyone know how to do it, ill really thanksfull for help.

I have this warning

warning: passing argument 1 of ‘atoi’ from incompatible pointer type [-Wincompatible-pointer-types]
   32 |         f = atoi(c);
      |                  ^
      |                  |
      |                  const char **
In file included from t9search.c:2:
/usr/include/stdlib.h:105:30: note: expected ‘const char *’ but argument is of type ‘const char **’
  105 | extern int atoi (const char *__nptr)

And this code

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXSIZE 100


struct persinfo
{
    char name[MAXSIZE];
    long phonumber;
};

void input_file(char c);
void input_number(const char **c, int i);

int main(int argc, char *argv[]){
    const char *temp = argv;
    int c;
    input_file(c);
    printf("\n");
    input_number(temp, argc);


    return 0;
}


void input_number(const char **c, int i){
    scanf("%c", *c);
    int f;
    f = atoi(c);
    if (!(f >= '0' && f <= '9')){
        printf("Error:Please enter a digit - > ");
    }
        if (i > 1){
        printf("%s", *(c+1));
    }
}



void input_file(char file){
    int i;
    char name[MAXSIZE];
    char phone[MAXSIZE];
    struct persinfo Contact;
    while((file = getchar()) != EOF){
        if ((file >= 'a' && file <= 'z') || (file >= 'A' && file <= 'Z')){
            strcpy(Contact.name, &file);
            printf("%s", Contact.name);
        }
         if (file >= '0' && file <= '9'){
            Contact.phonumber = file;
            printf("%c", Contact.phonumber);
        }
    }
}

int find(char str[], char ptr[]){
    int i, j, k;
    for (i = 0;str[i] != '\0'; ++i){
        for (j = i, k = 0; ptr[k] != '\0' && str[j] == ptr[k]; ++j, ++k);
        if (ptr[k] == '\0')
            return 1;
    }
    return 0;
}

So I if must work but i dont have solustion

  • `c` is a pointer to a pointer to `char`. `atoi` wants a pointer to `char`. But the overall approach is wrong anyway and there are many other issues. Also tell us what `input_number` is supposed to do. – Jabberwocky Oct 26 '22 at 10:07

1 Answers1

0

I see three issues here (may be more).

First, the assignment

const char *temp = argv;

assigns a pointer to an array of char pointers to a const char pointer (instead of assigning a char pointer, what probably was the intention).

Second, the function input_number is invoked

// Remember, now temp == argv
input_number(temp, argc);

but inside it there is this call

// Remember, now c == temp == argv
scanf("%c", *c);

which essentially overrides the value that the pointer that *c holds points to. What follows, since now c == argv, scanf overrides the value that the pointer to the first element of the array of program arguments points to, that is, the first character of the name of its executable. Indeed, if we try to print the executable name before and after such assignment (example code)

#include <stdio.h>

void f (const char **c) {
    printf("%s\n", *c);
    scanf("%c", *c);
    printf("%s\n", *c);
}

int main(int argc, char *argv[]) {
    const char *c = argv;
    f(c);
    return 0;
}

we receive (the input for scanf is a)

./prog
a/prog

what probably was not the intention.

Now, the third issue is, the assignment in the second issue works. But as far as I know, modifying a const value (**c in this case) results in undefined behavior. That is, now it works, but in some other execution, compiler, computer etc. it may not. Compare:


Edit: another issue is of course what Jabberwocky and the compiler say: you try to call atoi with a pointer to pointer to char, while it expects a pointer to char.


Edit: worth to note, in the condition

if (!(f >= '0' && f <= '9'))

the constants '0' and '9' are of type int (see [1]), so the comparisons are fine. But f is both declared as int and is assigned the result of atoi, therefore for me it is expected to be just an int, therefore in my opinion it would be clearer to write the comparisons using only integer constants, that is

if (!(f >= 0 && f <= 9))

Edit: another issue is that the function input_file is declared with a char parameter, that is

void input_file(char c);

but then it's called with an int parameter, that is

// Where c is declared as "int c;"
input_file(c);

It would be clearer in my opinion to keep the types the same: both chars or both ints.

An interesting thing would be to know why it works at all: how can you place an int variable, where there is a char variable expected? For one, C99 standard draft says that

[t]he type char, the signed and unsigned integer types, and the enumerated types are collectively called integer types.

So, char is an "integer type". Then, cppreference.com says that

[a] value of any integer type can be implicitly converted to any other integer type.

and later

if the target type can represent the value, the value is unchanged

But what is the value of c here? It is declared as

int c;

So, first, cppreference.com says that

[t]here are four kinds of storage duration in C:

  • automatic storage duration. The storage is allocated when the block in which the object was declared is entered and deallocated when it is exited by any means (goto, return, reaching the end).

and then it says that

[i]f an initializer is not provided:

  • objects with automatic storage duration are initialized to indeterminate values (which may be trap representations)

So, c in the moment of the conversion has an indeterminate value. What follows, it cannot be sure before actually executing the program whether "the target type can represent the value". What follows, we need to look for another rule about converting chars to ints: cppreference.com says that

  • otherwise, if the target type is unsigned, the value 2b , where b is the number of bits in the target type, is repeatedly subtracted or added to the source value until the result fits in the target type. In other words, unsigned integers implement modulo arithmetic.
  • otherwise, if the target type is signed, the behavior is implementation-defined (which may include raising a signal)

And the C99 standard draft says that

[t]he implementation shall define char to have the same range, representation, and behavior as either signed char or unsigned char.

Ultimately, not going into details, it is up to the particular implementation of C you use to decide what is going to happen when you try to call a function expecting a char with an int if the value is beyond range (and, again, we don't know whether it will be beyond range or not when the code will be executed).


Edit: another issue is, in the function input_file there is this line

strcpy(Contact.name, &file);

What it does is it copies a single character into a char array. An address of a single character is possibly not expected by strcpy because man 3 strcpy reads that

[t]he strcpy() function copies the string pointed to by src, including the terminating null byte ('\0'), to the buffer pointed to by dest.

Unfortunately, I see no clues neither in the man page nor on the internet how this function shall behave if there is no \0. In this answer to another question, Sourav Ghosh says that it is undefined behavior. And if he is true, I suppose that this is not what you expected.

user20276305
  • 95
  • 1
  • 7