I just returned to develop in C over eclipse and im having big issues im not sure how to solve, dont remember i used to have such when developing before. anyway i'll point u to 2 issues (i made my example easy-to-post in here):
#include <stdio.h>
int change_array(char *str, char *a[]) {
a[0] = "changed [0]";
if (fgets(str, 200, stdin) != NULL) {
}
return 0;
}
int main() {
char str[200];
char a[15][200];
change_array(str, a);
printf("a[0]: %s\n", a[0]);
printf("str: %s\n", str);
return 0;
}
getting a warning in line "change_array(str, a)": passing argument 2 of ‘change_array’ from incompatible pointer type [enabled by default] - why??
after running my 'doing-nothing' code sample output is:
some-value
a[0]: � <------- wired characters appear
str: some-value
The issue is here... int change_array(char *str, char *a[])
The dimension of a is undefined, so it doesn't know how far to step each *a and a is an array of pointers to char. However, you are passing in an array of arrays of 200 char. Thus the incompatible types error.
I believe your issue goes away with...
int change_array(char *str, char (*a)[200])
in which case a is a pointer to an array of 200 chars and the compiler now knows how far to step each index of a
Related
I want to store data in different files. Therefore I want to create files as follows: data_1.log, data_2.log, ..., data_N.log. The appendix .log is not necessary but would be nice. All my approaches failed so far. Here is one sample that is probably close to what I need:
#include <stdio.h>
#include <string.h>
char get_file_name(int k){
int i, j;
char s1[100] = "logs/data_";
char s2[100];
snprintf(s2, 100, "%d", k);
for(i = 0; s1[i] != '\0'; ++i);
for(j = 0; s2[j] != '\0'; ++j, ++i){
s1[i] = s2[j];
}
s1[i] = '\0';
return s1;
}
int main(){
char file_name[100];
for(int k=0; k<10; k++){
// Get data
// ...
// Create filename
strcpy(file_name, get_file_name(k));
printf("%s", file_name);
// fp = fopen(file_name, "w+");
// Write data to file
// print_results_to_file();
// fclose(fp);
}
return 0;
}
At the moment I get the following errors which I don't understand:
string.c: In function ‘get_file_name’:
string.c:14:12: warning: returning ‘char *’ from a function with return type ‘char’ makes integer from pointer without a cast [-Wint-conversion]
return s1;
^~
string.c:14:12: warning: function returns address of local variable [-Wreturn-local-addr]
string.c: In function ‘main’:
string.c:24:27: warning: passing argument 2 of ‘strcpy’ makes pointer from integer without a cast [-Wint-conversion]
strcpy(file_name, get_file_name(k));
^~~~~~~~~~~~~~~~
In file included from string.c:2:
/usr/include/string.h:121:14: note: expected ‘const char * restrict’ but argument is of type ‘char’
extern char *strcpy (char *__restrict __dest, const char *__restrict __src)
^~~~~~
Is there a more simpler way to create such filenames? I can't believe that there isn't one.
There are various issues with this code and rather than correcting them one by one here’s an alternative approach. It’s not the only one but it’s simple and should be easy to understand and adapt:
#include <stdio.h>
void get_file_name(int k, char* buffer, size_t buflen) {
snprintf(buffer, buflen, "logs/data_%d.log", k);
}
int main() {
const size_t BUFLEN = 50;
char file_name[BUFLEN];
for (int i = 0; i < 10; i++) {
get_file_name(i, file_name, BUFLEN);
printf("%s\n", file_name);
// Code for writing to file.
}
}
A few details:
Rather than attempting to return (pointers to) memory, this function passes a buffer that is written to. It’s up to the caller to ensure that the buffer is big enough (this is always the case here, but if the actual filenames are longer, you should add logic that inspects the return value of snprintf and performs appropriate error handling).
The actual logic of the function requires only a single call to snprintf, which already performs everything you require, so it’s unclear whether having a separate function is even necessary or helpful.
The above uses variable-length arrays. If you want to ensure constant buffers, you can use a #define instead of a const size_t variable for the buffer length. However, using a variable-length array here is fine, and some compilers even convert it into a constant array.
As mentioned in comments, it’s important that you (a) read and understand the documentation of the functions you’re using, and (b) read and understand the compiler error messages.
The function get_file_name has return type char
char get_file_name(int k){
but it returns an object of type char *
char s1[100] = "logs/data_";
//...
return s1;
Moreover the returned pointer points to a local array s1 that will not alive after exiting the function.
In this call
strcpy(file_name, get_file_name(k));
the type of the second argument (that is char according to the function get_file_name declaration) shall be char *.
There is neither the function print_results_to_file declaration nor its definition.
According to the C Standard the function main without parameters shall be declared like
int main( void )
I would write the function get_file_name the following way
#include <stdio.h>
#include <string.h>
char * get_file_name( char *file_name, size_t n, size_t padding )
{
const char *common_part = "logs/data_";
snprintf( file_name, n, "%s%zu", common_part, padding );
return file_name;
}
int main( void )
{
enum { N = 100 };
char file_name[N];
for ( size_t i = 0; i < 10; i++ ) puts( get_file_name( file_name, N, i ) );
}
The program output is
logs/data_0
logs/data_1
logs/data_2
logs/data_3
logs/data_4
logs/data_5
logs/data_6
logs/data_7
logs/data_8
logs/data_9
There are several problems with your code, but the biggest one is that you are trying to return a pointer to a local variable from get_file_name.
This is a big no no since the memory allocated for char s1[100] in get_file_name is freed immediately after return.
The rest of the errors are because you forgot the * in char get_file_name(int k).
There are several possible solutions:
Pass in a char array for the function to fill.
Use a global variable (This is considered a bad practice).
Dynamically allocate the memory.
Make the local variable static (this is a bit hacky, but legal)
Your errors are easily explained:
get_file_name should return a char but you create a char[] and return this(it isthe same as char*)
get_file_name returns the adress of an array that is created in the function itself. After the function ends, the array may be overwritten. Add the array as parameter or use malloc
strcpy does not work because it expects a char* (char[]) and not a char. get_file_name returns a char.
print_results_to_file is not defined. You may need to include other files you use in the program (e.g. if the function is implemented in a file func.c the prototype should be in a file called func.h that is included via #include "func.h".
completely new to C. just trying to get the hang of linux and C programming by getting John Bentley's Anagram (column 2 I believe)program to run. Pretty sure ive copied this code verbatim(had to add headers, etc) but im receiving a warning, which when compiled and run with my squash.c program gives an undesired output. ill admit, i dont even know how this charcomp function behaves, or what it even does. (some enlightenment there would also be nice).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int charcomp(char *x, char *y) {return *x - *y;}
#define WORD_MAX 100
int main(void)
{
char word[WORD_MAX], sig[WORD_MAX];
while (scanf("%s", word) != EOF) {
strcpy(sig, word);
qsort(sig, strlen(sig), sizeof(char), charcomp);
printf("%s %s\n", sig, word);
}
return 0;
}
Here's the warning.
sign.c:13:41: warning: incompatible pointer types passing 'int (char *, char *)'
to parameter of type '__compar_fn_t' (aka 'int (*)(const void *, const
void *)') [-Wincompatible-pointer-types]
qsort(sig, strlen(sig), sizeof(char), charcomp);
^~~~~~~~
/usr/include/stdlib.h:766:20: note: passing argument to parameter '__compar'
here
__compar_fn_t __compar) __nonnull ((1, 4));
^
The qsort() function takes a comparison function as a fourth argument, with the following signature:
int (*compar)(const void *, const void *)
Therefore, to avoid compiler warnings, you have to modify you charcomp() function in the following way, to fit that signature:
int charcomp(const void *x, const void *y) { return *(char *)x - *(char *)y; }
Your charcomp function just takes two char* pointers to and compares first their first characters.
Consider the following program:
#include <stdio.h>
void foo(char** string)
{
printf("%s", string[0]);
}
int main()
{
char* a = "blahblah";
foo(&a);
return 0;
}
It works fine as it is, but if I substitute
char* a = "blahblah";
with
char a[] = "blahblah";
it does not work.
I get the warning expected 'char **' but argument is of type 'char (*)[9]', and a segmentation fault.
I was under the impression that char[] and char* are the same thing, so a pointer to each of them would also be the same.
(windows with mingw, gcc 4.8.1)
Thank you
In most cases these two statements behave the same, with two exceptions. One exception is when applying the & operator. When you apply & to an array(e.g. a[]), you got the address of the whole array. This value is identical to the address of the first element of the array, so &a == a (their types are different tough). You can try a simple example here: http://ideone.com/96w3oa
Ok. Now we can see why you got a segmentation fault. Because &a is equal to a, your string[0] actually does an extra deference. The correct way would be:
printf("%s", string);
or
printf("%s", (&string)[0]);
if you use
char a[] = "blahblah";
For more information regarding the difference between the two statements you tried, please refer to this post (especially the post by John Bode): What is the difference between char s[] and char *s?.
Here is also a very good explanation:
http://publications.gbdirect.co.uk/c_book/chapter5/arrays_and_address_of.html
When you are passing the array to the foo function, you should do in this manner.
#include<stdio.h>
void display(char *);
int main()
{
char arr[]="Do something";
display(arr);
return 0;
}
void display(char *string)
{
printf("%s",string);
}
else you might be getting segmentation error.while using &array_name, you actually pass the address of the starting element.
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] = '*' */
}
}
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;