Error invalid operands to binary expression - c

I've been working on readability and I really am stuck as to what I've done wrong/what I'm missing.
#include <stdio.h>
#include <math.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
int main() {
string text = get_string("Text: ");
int sentences = 0;
int numberOfCharacters = strlen(text);
string characters[numberOfCharacters];
int words = 0;
for (int i = 0; i == numberOfCharacters; i++) {
if (isspace(characters[i]) == 0) {
words ++;
}
}
for (int i=0; i < numberOfCharacters; i++) {
if (text[i]=='.') {
numberOfCharacters++;
}
}
int averageWords = characters / words * 100;
int index = 0.0588 * round(characters) - 0.296 * round(sentences) - 15.8;
printf("Grade %d \n", index);
}
The error I get from that, using help50, is: readability.c:26:35: error: invalid operands to binary expression ('string [numberOfCharacters]' and 'int')
Which I don't understand, so please if possible help :)

In cs50 string is a typedef of char*, so what you have there is:
char *characters[numberOfCharacters];
Which is an array of pointers, they are not initialized in any way, in your next statements you accessing these unitialized values and you are passing an incompatible argument to isspace.
Furthermore, the expression:
int averageWords = characters / words * 100;
Is odd, you're dividing an array of pointers to char (wich decays to a pointer, but that's beside the point), by an int. That's where the error stems from, but you need to correct the rest.
Not to mention round(characters) which is also very strange, that function expects a double argument, but again, you are passing to it an array of pointers.

The name string is defined as an alias for the type char *. So this declaration
string characters[numberOfCharacters];
is equivalent to the declaration
char * characters[numberOfCharacters];
So in this expression
isspace(characters[i]) == 0
the argument characters[i] has the type char * while the function expects an argument of the type int.
So you need at least to declare
char characters[numberOfCharacters];
But in any case this loop
for (int i = 0; i == numberOfCharacters; i++) {
if (isspace(characters[i]) == 0) {
words ++;
}
}
does not make a sense because the array characters was not initialized.
It seems within this loop you were going to use text instead of characters.
This expression
int averageWords = characters / words * 100;
is entirely wrong and does not make a sense. You are trying to divide a pointer ( after implicit conversion the array characters to a pointer to its first element) by an integer. But such an operation is not defined for pointers.
So it is unclear what the program does.

First Issue:
string is defined as char * so this is wrong:
string characters[numberOfCharacters];
That is giving you an array of strings, not a string of length numberOfCharacters
Change that to this:
char characters[numberOfCharacters];
Second Issue:
characters is uninitialized when first used, you could of meant to use text instead in the loop
Third Issue:
Performing math (round(characters) and characters / words * 100) on a string or array is certainly wrong and makes no sense, so I am not sure what you are attempting to do here
I reviewed the clear issues, but since it is unclear what your program is trying to do, I cannot provide further feedback

Related

How to fix "error: subscripted value is neither array nor pointer nor vector" in macros in c language?

I have such code:
typedef struct dArrString
{
char** arr;
int locLength;
int length;
} dArrString;
#define D_ARR_STRING(NAME, ARR_STRING)\
NAME.arr = (char**) malloc(0 * sizeof(char*))\
NAME.locLength = 2;\
NAME.length = 0;\
printf("%s", ARR_STRING[0]);
int main()
{
dArrString stos;
char emptyStr = {'\0'};
D_ARR_STRING(;stos, emptyStr);
return 0;
}
Problem is in ARR_STRING[0] in D_ARR_STRING macros, becuse after compiling this code I got such an error:
error: subscripted value is neither array nor pointer nor vector
printf("%s", ARR_STRING[0]);
How can I fix this or what should I change to?
ARR_STRING is the second parameter to the macro, which is passed as emptyStr.
emptyStr is declared as a char:
char emptyStr = {'\0'};
meaning that it is one single Character (like A, or Z).
The compiler is correct that you are trying to take the subscript ([ ]) of emptyStr, and emptyStr is not an array, nor a pointer, nor a vector.
If you want to fix it, you need to make the second parameter an array.
Most probably, you want:
char emptyStr[50] = ""; // I'm not sure what size you need, so I made it 50.
List of problems:
You have a weird semi-colon before stos for no clear reason.
You are calling malloc for 0 bytes.
You are treating variable emptyStr, a single char, like its an array of characters.
You have a substantial block of code in a macro for no good reason, when a function would do just fine.

Newline Constants in C

My code:
#include <stdio.h>
int main() {
const int LENGTH = 10;
const int WIDTH = 5;
const char NEWLINE ='\n';
int area;
area = LENGTH * WIDTH;
printf("value of area : %d", area);
printf("%c", NEWLINE);
return 0;
}
In the above code the output:
value of area: 50
Process returned 0 (0x0) execution time : 2.909 s
Press any key to continue.
There is a new line inserted, but when I change NEWLINE="\n" despite knowing it is a char type, there is no error prompted by the compiler and no newline printed out. Why???
Also, I modified my code as,
#include <stdio.h>
int main() {
const int LENGTH = 10;
const int WIDTH = 5;
const char NEWLINE ='\n';
const char k="hjk";
int area;
area = LENGTH * WIDTH;
printf("value of area : %d", area);
printf("%c", NEWLINE);
printf("%c", k);
return 0;
}
The output is only the area calculated and the new line but k is not printed out. I also find this very weird! Can you please give suggestions?
Please be kind enough with the suggestions and point out my mistakes because I am a beginner at C.
The problem is that you are trying to save a string as a char, so you have to change const char k = "hjk" to const char k[]="hjk" and print it using %s instead of %c.
#include<stdio.h>
int main() {
const int LENGTH = 10;
const int WIDTH = 5;
const char NEWLINE ='\n';
const char k[]="hjk";
int area;
area = LENGTH * WIDTH;
printf("value of area : %d", area);
printf("%c", NEWLINE);
printf("%s", k);
return 0;
}
Some clarification: if you save a "string" without specifying that it is an array of characters char[], if you try to print it as a char %c a warning would be generater (warning: incompatible pointer to integer conversion initializing 'const char' with an expression of type 'char [4]') and if you try to print it as a array of characters %s (string) you are going to receive a segmentation fault.
when I change NEWLINE="\n" despite knowing it is a char type, there is no error prompted by the compiler
const char NEWLINE = "\n"; is invalid C. The reason why it is invalid is explained in detail here: "Pointer from integer/integer from pointer without a cast" issues
The compiler is not required to produce an "error", but it is required to produce some sort of diagnostic message. See What must a C compiler do when it finds an error?
Why your compiler decided to spew out a binary regardless of getting fed invalid C is anyone's guess. You have to ask the people who made the compiler. In case of gcc, you won't find an answer, because this is completely undocumented behavior.
And therefore, any output you get from such a "non C" program is also completely non-deterministic, unless a compiler documented the behavior among non-standard compiler extensions. gcc did not.
Similarly, const char k="hjk"; is also invalid C.
k seems an array of char.
Try to use:
const char k[] = "something";
printf("%s", k);
The statement const char k="hjk"; is not valid C code. Apparently, your compiler accepts it and assigns the memory address where the literal string "hjk" begins to k. Both a memory address and a char are implemented as integer numbers, so the memory address is interpreted as the numeric code for a character.
Because k is now, most likely, an unprintable character, printf("%c", k); will print nothing.
Exactly the same happens when you do const char NEWLINE ='\n';.

C sort array of strings with qsort and strcmp - warning: incompatible pointer type

I tried to sort an array of strings with qsort but got this warning:
warning: passing argument 4 of 'qsort' from incompatible pointer type
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAX_PRODUCTS 1000
int main (void) {
int i, index = 0, isUnique;
char products[MAX_PRODUCTS][100];
char product[100];
int count[MAX_PRODUCTS];
FILE * fp;
fp = fopen ("one.txt", "r");
// Read words from file and put in array if unique
while (fscanf(fp, "%s", product) != EOF){
isUnique = 1;
for (i=0; i<index && isUnique; i++){
if (strcmp(products[i], product) == 0){
isUnique = 0;
}
}
if (isUnique) {
strcpy(products[index], product);
index++;
}
else {
count[i - 1]++;
}
}
qsort(products, MAX_PRODUCTS, sizeof(char*), strcmp);
fclose(fp);
return 0;
}
I also tried a custom function to compare strings but this didn't worked either.
What can I do to fix it?
qsort is documented on the Microsoft website where it states:
compare
Pointer to a user-supplied routine that compares two array elements and returns a value that specifies their relationship.
Use this:
int compare (const void * a, const void * b)
{
return strcmp((char*)a, (char*)b );
}
the following way:
qsort(products, MAX_PRODUCTS, 100, compare);
You tell qsort(), that you want to sort an array of pointers, but have indeed an array of arrays!
This gives you an array of pointers:
char *products[MAX_PRODUCTS]
for (int i = 0; i < sizeof(products)/sizeof(*products); i++) {
products[i] = malloc(100);
}
You could also sort the whole array members, but this involves swapping the whole strings (strictly spoken, the whole arrays, even if the strings are shorter) a multitude of times, which can be quite inefficient. It is much faster to only swap the pointers.
Furthermore, the signature of strcmp() does not match the prototype, that qsort expects. So you should wrap it in a compare-function with prototype
int compar(const void *, const void *);
as shown in the manpage.
Then, the compiler should not complain any more.
You actually have more problems than the warning you get:
You always sort MAX_PRODUCTS elements of the products array, no matter how many elements are actually valid (you sort uninitialized and indeterminate strings).
You say that the element-size of the products array is sizeof(char*), but products is an array of arrays, so each element of products is sizeof producst[0] large.
Now for the warning itself: The declaration of strcmp is
int strcmp( const char *lhs, const char *rhs );
while the comparison function passed to qsort is
int (*comp)(const void *, const void *)
The argument types are different. A seemingly possible solution is to cast the strcmp pointer to the correct type:
typedef int (*sortfun_type)(const void *, const void *);
// After the loop the variable index should be the number of strings read
qsort(products, index, sizeof products[0], (sortfun_type) &strcmp);
As noted in a comment, this is technically not correct (but should work anyway). The proper solution is to write a wrapper-function with the correct arguments types, which then calls strcmp (as shown by others).

Why does the GCC Compiler allows us to declare zero length strings (directly) and negative length strings (indirectly)?

/*implementation of strrev i.e. string reverse function*/
#include<stdio.h>
#include<string.h>
/*length of the string i.e. cells in the string*/
static const unsigned int MAX_LENGTH = 100;
//static const int MAX_LENGTH = -100;
/*reverses the string*/
void reverseString(char[]);
/*swaps the elements in the cells of a string*/
void swap(char[], int, int);
/*runs the program*/
int main()
{
char string[MAX_LENGTH];
//char string[0]; //no error!
//char string[-1]; //error!
gets(string);
reverseString(string);
printf("\n%s", string);
return 0;
}
void reverseString(char string[])
{
int i;
for(i = 0; i < (strlen(string) / 2); i++)
{
swap(string, i, (strlen(string) - 1 - i));
}
}
void swap(char string[], int i, int j)
{
int temp = string[i];
string[i] = string[j];
string[j] = temp;
}
Look at the main function. If you replace the first line "char string[MAX_LENGTH];" with "char string[-1];", the compiler shows error. (because string of negative length makes no sense). However, if you replace the 7th line of this code (where I declared const MAX_LENGTH) with the code written in comments in line 8 (in which MAX_LENGTH is assigned a -ve value), there is no compilation error. Why?
Also, why there is no error in declaring zero length string. How does zero length string makes sense to compiler but not a negative length string?
Because it's not the same thing.
In the first case, you're defining an array, using a fixed, compile-time size
In the second case, you're defining a variable length array or VLA.
The compiler does the allocation at run time in the second case (with this -100 value it isn't going to end well), because the const isn't really a constant in C, it just tells the compiler you aren't to change the value (and also allows some optimizations). So the result is undefined behaviour (more here: Declaring an array of negative length)
If you want the same behaviour use a #define
#define MAX_LENGTH -100 // will raise a compilation error
or as suggested in comments, an enumerated constant:
enum { MAX_LENGTH = -100 }; // will raise a compilation error
If you want to protect your declarations, use assert
assert(MAX_LENGTH > 0);
char string[MAX_LENGTH];
As for the zero-length element, no need to repeat what's already been answered: What's the need of array with zero elements? (in a nutshell, it's useful at the end of a structure to be able to have varying length)

incompatible pointer to integer although using char of arrays

I'm new to the world of C programming, and I as trying to code a primitive, terminal-based version of the "Hangman" game.
One of the steps doing this (or at least the way I am working on), is to create a second char array (next to the original char array that stores the word one needs to guess), filled with "*" for every Char of the original array, and display it. Although the rest of the programming part is not there yet (since I am not finished with it yet), I doubt it is relevant for now (however I allready know how to proceed, that is if I weren't bothered by some error-messages)....
Here's the code I have so far:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
void hiddenArray(char array[]);
char *secretWord;
char *arrayCover;
char letter;
int main(int argc, char *argv[]){
secretWord = "Test";
printf("Welcome to the Hangman!\n\n");
hiddenArray(secretWord);
printf("What is the hidden Word?: %c\n", *arrayCover);
printf("Guess a letter\n");
scanf("%c", &letter);
}
void hiddenArray(char array[]){
int size,i;
size = sizeof(*array);
for (i=0;i<size-1;i++){
*(arrayCover+i) = "*";
}
}
Now I have two issues... the first one:
I don't understand the error message I am getting after compilation:
pendu.c:41:19: warning: incompatible pointer to integer conversion assigning to 'char' from 'char [2]' [-Wint-conversion]
*(arrayCover+i) = "*";
^ ~~~
1 warning generated.
And my second question: the second Array created, filled with "*" is not being displayed, what did I do wrong?
I'd love for some help, cheers!
Your program have some errors to be corrected .
1) Your *arraycover is pointing to some unknown value, You have not initialized it.
2) sizeof(*array) should be sizeof(array)
3) *(arrayCover+i) = "*" should be *(arrayCover+i) = '*';
I suggest you not to create too many global variables when you dont really need them
Create char secretWord[100] = "Test" instead of char *secretWord
Try this
size = sizeof(arrayCover)/sizeof(char);
for (i=0;i<size-1;i++){
*(array+i) = '*';
}
Despite of all these, I think you need to allocate memory for arrayCover
arrayCover = malloc(sizeof(char) * number_of_elements);
"*" is a string. Use '*' instead to get the char.
"*" is a string which also contains \0 also, resulting to 2 characters. Instead use '*' which is just a character.
The function hiddenArray has the formal argument array which need to be used locally instead of arrayCover as below,
void hiddenArray(char array[]){
int size,i;
size = sizeof(array)/sizeof(array[0]);
for (i=0;i<size-1;i++){
*(array+i) = '*'; /* Or array[i] = '*' */
}
}

Resources