C Pointers and Arrays Incompatible Types - c

So I was wondering why I can't do this.
int main(int argc, char **argv){
FILE *src;
char filePath[261];
filePath = argv[1];
The last line is where there is a compiler error. What's the difference between char[] and char*? How would I fix this code so I can set filePath equal to argv[1].
Thanks in advance.

Use
strcpy(filePath, argv[1]);
and live happy. Don't forget to check argv[1] for being NULL and don't forget to see if argc is > 1.
Your filePath variable is a fixed-size array which is allocated on the stack and argv[i] is a pointer to some memory in the heap. Assigning to filePath cannot be done, because filePath is not a pointer, it is the data itself.

Because filePath is an array and it's not allowed to modify the address of an array in C.
You can use the string family to copy the strings.

You need to have:
FILE *src;
char *filePath;
filePath = argv[1];
since filePath must point to argv, not to an array of 261 bytes. If you want, you can copy the argumenti into the array:
FILE *src;
char filePath[261];
strcpy(filePath, argv[1]);
or better, to avoid risking copying more bytes than you have available (which would result in disaster):
FILE *src;
char filePath[261];
strncpy(filePath, argv[1], sizeof(filePath));
or again
#define MAX_FILESIZE 261
FILE *src;
char filePath[MAX_FILESIZE];
strncpy(filePath, argv[1], MAX_FILESIZE);

Q: What's the difference between char[] and char*?
A: Often times, you can use them interchangeably.
But here, you're "attempting to use an array name as an lvalue" :)
Here's a good explanation:
http://eli.thegreenplace.net/2011/12/15/understanding-lvalues-and-rvalues-in-c-and-c/
Here's a short summary of "what's legal, and what's not":
http://msdn.microsoft.com/en-us/library/bkbs2cds.aspx

Related

unable to get filename from argv[1] in C

I'm trying to make a program which makes a copy of the file you put in, only then with a reversed filename (eg. input.txt = txt.tupni).
I start my program with
int main(int argc, char **argv) {
When I use printf("%s",argv[1]) I can see the file name which has been put in. However, when I try to manipulate it I can't get it to work.
char name = argv[1] doesnt work,
neither does char name[] = argv[1] work
All I want is either a char array or a piece of malloc memory which has all of the characters.
argv is of type char **, so argv[1] is of type char *. So that's the type of the variable you want to assign this to.
char *name = argv[1];
You can't declare name as char [] and initialize it with a char *. Only a string literal may be used for initialization.
If you want to make a copy of the string rather than have another pointer to it, you can use strdup which allocates memory for the copied string and copies it over.
char *name = strdup(argv[1]);
Don't forget to free it when you're done with it.
You need to use a function like strcpy to accomplish this, as well as know the string length.
Here's what you do:
int len = strlen(argv[1])
char *buffer = (char*)malloc(len + 1);
if(buffer != NULL)
{
strcpy(buffer, argv[1]);
// copy the file etc.
}

Proper use of Char**

I am new to C and came across a Char**, for example in the getline function. I have found several topics regarding this type but none of it explained how to actually use it. I understood the differences between Char[], Char* and Char**, but how can I access the content stored in a Char**?
Could someone explain that to me? Thanks in advance!! :)
So, for example i am trying to use the getline function to extract single lines from a file and to store them:
FILE *fp = fopen(myfile,"r");
size_t fsize;
char **string;
ssize_t bytes_read =0;
while ((bytes_read = getline(string, &fsize, fp))>0) {
// How to handle the content of string now? Is every line from the File stored in the Char** now?
}
Almost always when a function asks for a char** or a ** in general, you're expected to give it the address of a pointer variable. In this case the address of a char*. The address of operator is &, thus you should call getline like this:
char *string = NULL;
size_t size = 0;
while ((bytes_read = getline(&string, &fsize, fp))>0) {
// use string here...
}
free(string);
There are of course exceptions to the rule of ** functions wanting an address of, but getline isn't one of them.
In the case of getline it requires the memory address at which to store the memory address of the first character in the line you've read.
I.e. it needs a pointer to a pointer or a char**.
Your string will be stored in *string.
Of course you can get this information from the documentation :).

strcat in C error segmentation

#include <stdio.h>
#include <string.h>
int main() {
char tab[2]={"12"};
FILE *outfile;
char *outname = "/home/dir/";
printf("%s", strcat(outname,tab));
outfile = fopen(strcat(outname,btab), "w");
if (!outfile) {
printf("There was a problem opening %s for writing\n", outname);
}
}
I have this error: Segmentation Fault.
How can I fix it?
At least two errors:
char tab[2] = {"12"};
You'd better use tab[3] or even better tab[] -- you need one extra char for the terminating NUL character.
Also,
char *outname = "etc...";
creates a constant string in the data segment of the executable -- it can't be overwritten, since strcat is using its first parameter to concatenate the two strings. So when strcat() tries to do so, it segfaults. Use
char outname[50]; // something big enough
strcpy(outname, "/home/dir");
instead.
outname is a string literal and string literals are not modifiable. Modifying a string literal is undefined behavior.
outname is Const pointer so once you have entered some thing in it, you can't modify it.
However if you want to copy things in it, make a char array of the size equal to tab[] array because here the size of string to be copied is known. Most of the time char pointers like OUTNAME are used when you are taking input from a user once and you don't know how long that input will be.
In your code,
char *outname = "/home/dir/";
outname is a string literal and hence when used with strcat, it does not have enough length to hold the concatenated string.This results in segmentation fault.
Same is the case had you declared it as below,
char outname[] = "/home/dir/";
The solution for this to declare the size of the outname big enough to hold the concatenated string.
char outname[80] = "/home/dir/";

C Arguments character Array

I would like to pass in arguments and output them as an array of characters or string. What is the easiest way to do this? Once I have them as an array of characters I want to be able to manipulate the array. I was able to pass them in and use a character pointer to traverse through the string but I'd like to use a char array. Is there any easy way to do this? Im pretty new to C, here is what I have so far.
if(argc != 3){
printf("incorrect number of arguments, program needs 3\n");
exit(1);
}
char s1[20];
s1 = (char*)argv[1];
char s2[20];
s2 = (char*)argv[2];
printf("String1 is %s\n", s1);
printf("String2 is %s\n", s2);
exit(0);
The strings pointed to by the argv array are modifiable, you can just modify the strings pointed to by the argv array, there is no need to copy them.
From the C standard:
(C99, 5.1.2.2.1p2) "The parameters argc and argv and the strings pointed to by the argv array shall be modifiable by the program, and retain their last-stored values between program startup and program termination."
You can simply print the values of argv directly:
printf("String1 is %s\n", argv[1]);
printf("String2 is %s\n", argv[2]);
If you need to modify the strings, here is how you would do that
char *newString1 = malloc(strlen(argv[1]) + 1 + charactersToAdd); // add one for null termination.
strcpy(newString1, argv[1]);
// manipulate newString1 however you choose
printf("String1 is %s\n", newString1);
free(newString1);
argv[1] and argv[2] are already pointers to character arrays, so you can use those directly. Moreover (see #ouah's post), the strings are already mutable, so you might not need anything beyond this at all.
If you really want to have a scope-local array, you need to use the C99 feature called "variable-length arrays", since the string lengths are only known at runtime:
#include <string.h>
int main(int argc, char * argv[])
{
char s1[strlen(argv[1]) + 1];
strncpy(s1, argv[1], sizeof s1);
// ...
}
Alternatively you could malloc enough space for a copy of the string (say char * s1 = malloc(strlen(argv[1]) + 1);), but then you wouldn't have a local array after all (and you might as well use the original strings, unless you really wanted to make a copy).
argv is already char* (actually an array of an array), however, they are noted const as in "do not modify" ;). What you want is actually making a copy of them so you can manipulate them freely:
char str[40];
strcpy (str,argv[1]);
Now you can manipulate str as you wish.

How to assign pointer to global variable?

I have to split up a command line argument in order to determine the file type. In order to do this, I'm using
char fileName; //global variable, just below function prototypes
char *fileType;
fileType= strtok(inputFile, "."); //first string split
fileName= (int) &fileType; //store the file name for further use
fileType= strtok(NULL, "."); //get the file type
The tokenizer function is working, but in the interest of keeping redundant code to a minimum, I want to store the filename, as I will have to create a new file with the same name, but different extension later on.
In the debugger, the the fileName variable never gets used. Why?
About
char fileName; //global variable, just below function prototypes
if fileName is supposed to be a string then it must be a pointer to the first char in that string (i.e. char *fileName).
if fileName is suposed to be a pointer to a string, then it should be declared as char **fileName.
About
char *fileType;
if this is a local variable, and fileName is a pointer to it, then after the function return it will be destroyed and the pointer will point to unknown data.
About
fileName= (int) &fileType; //store the file name for further use
this seem non-sense to me. Why cast the address of fileType to an integer? I guess the compiler complained because fileName is a char and not a char * and you noticed this would fix the error. Don't do this kind of fixes without understanding what you're doing, because programming like that just leads to esoterical code which must probably won't work as intended anyway.
So, if fileName is defined as char * then just do fileName = fileType. Else, if fileName is declared as char ** then do fileName = &fileType;
About
fileType= strtok(NULL, "."); //get the file type
if strtok() can return a pointer to a new string, and fileName is declared as char *, then whatever you stored previously in it wouldn't be meaningful anymore. In this case fileName would need to be a char ** (a pointer to a string) which I proposed in my first comment.
You need to use a char array along with strcpy.
Like this:
#define MAX_FILENAME_SIZE 200
char fileName[MAX_FILENAME_SIZE];
int f()
{
fileType = strtok(inputFule, ".");
// then use strcpy
strcpy(fileName, fileType);
}
A char global would only store one character.

Resources