add string to given command line argument in C - c

Hello i just started to programm in C and i am trying to read a file and give the file name as argument without the ending .txt . I want to add .txt in my code : ./myexample.exe file
if i use file.txt there is no problem but i dont know how to change argv[1]
i tried char *n = argv[1] + ".txt"; it doesnt works and i dont know anything else..
int main(int argc, char* argv[]) {
char *n = argv[1] +".txt";
FILE *fp1;
fp1 = fopen(n , "r");
Thats what i get if i use char *n = argv[1]+".txt"
error: invalid operands to binary + (have 'char *' and 'char *')

In your code,
char *n = argv[1] +".txt";
does not do what you think it does. In C, the + cannot be used to concatenate strings.
FYI, from C11, chapter §6.5.6
For addition, either both operands shall have arithmetic type, or one operand shall be a
pointer to a complete object type and the other shall have integer type. (Incrementing is
equivalent to adding 1.)
Both the operands cannot be of pointer-to-object type.
If you meant to concatenate strings, use strcat() but make sure
the destination is modifiable (attempt to modify string literal is UB)
the destination got enough space to contain the final result (shorter destination lead to access out of bound memory invoking UB, again).

You can't concatenate strings with +. Use strcpy and strcat:
char n[256];
strcpy(n, argv[1]);
strcat(n, ".txt");
Make sure that n is large enough to hold the filename + extension.

This is kind of annoying to do safely: you need to be careful to make a big enough char array to hold the whole string. One way:
size_t arglen=strlen(argv[1]);
char* filename=malloc(arglen+5); //Enough to hold the whole string
strcpy(filename,argv[1]);
strcat(filename,".txt");
Be sure to free the pointer later.

Related

Why we didn't use * during dereferencing the pointer?

In the below code, we get a pointer from strdup(source) and we store it in a pointer named target.
Now, when we print the string using pointer, we don't add * at the beginning of the pointer: why is it so? As I studied whenever we want to dereference any pointer we use *pointer_name. If we add * in the below code, we get an error.
I am very beginner, so pls ans in easy words.
#include<stdio.h>
#include<string.h>
int main()
{
char source[] = "Programming";
char* target = strdup(source);
printf("%s\n",target);
return 0;
}
printf expects a char pointer in the place of the %s specifier.
https://en.cppreference.com/w/c/io/fprintf
char* target = strdup(source);
printf("%s\n",target);
Why we don't use *target in the code above?
The explanation is quite simple, as already stated in previous answers: target has type char pointer, which is exactly what printf() wants in the above call.
Now, printf() is a little complicated because its semantic is not simple - basically it accepts zero or more arguments after the first, of any type (possibly applying promotion). But if we use strdup() again, maybe it is simpler:
char* target2 = strdup(target);
Here, if you wrote strdup(*target), the compiler might warn that you are passing a char instead of a pointer to char.
strdup() returns a char*, hence the char* type of target. target holds a pointer to the first character in an array of chars. printf("%s", string) expects string to be a char*, so there’s no reason to do anything to target; just pass it to printf().
If you dereferenced target, you would get a single char (P in this case). printf() would then complain that you had supplied a character instead of a string (pointer to character). Even worse, the program could compile, and then printf() would try to print the string at address P (0x50), which would result in probably unwanted behaviour.
When working with arrays—a string is a type of array—you rarely want to dereference the array.

C string setting character array to argv[1]

if I have a program as follows:
int main(int argc, char** argv) {
char s[32] = argv[1];
printf("entered char is %s\n", s);
}
Why do I get an error: array initializer must be an initializer list or string literal, during compile time?
Isn't argv[1] a string and isn't is legal to do
char s[32] = "A test string"
You can't initialize an array using a pointer like that. Instead you have to copy the string after declaration:
char s[32];
strcpy(s, argv[1]);
Note that you should really check if at least one argument is provided before doing that (by checking argc). Also note that unless you want to modify the string provided in the argument, there's really no need to keep a second copy of the string.
Oh and you might want to use strncpy instead of plain strcpy, to avoid a possible buffer overflow situation. Remember that strncpy will not terminate the string if the source is to long, so you need to do it explicitly.
Expression char s[32] = argv[1]; causes error because by doing s=argv[1] you are trying to change base address of s, which is not possible as s is constant pointer.
Use strcpy() to copy argv[1] into s
char s[32];
strcpy(s,argv[1]);
Asking a question like this means - you are not aware of certain rules. In C, there are a few possible ways you can initialize an array. And the compiler told you about that when it saw it violating the rule. It says it must be string literal or initializer list. The one you provided is not any of this. It is simply a pointer and you can't initialize an array by putting it in the right side of the = assignment operator.
char s[]="hello";
char s[]={'h','e','\0'};
Select one as shown above. First is using literal and second using initializer list. In your case you can't use any of these - what's the way? strcpy at your rescue. Before you use like the other answer showed make sure buffer is big enough to hold stuff you copy.

C fscanf formatting

I'm quite new to C and I'm having a bit of trouble with these pieces of code:
char word[STRING_LEN];
while(num_words < ARRAY_SIZE && 1 == fscanf(infile, "%79s", &word))
When I try to compile, I get the warning:
format '%s' expects argument of type char *, but argument 3 has type
char (*)[80].
Now this is remedied by using &word[0]. Now, shouldn't these both point to
the address at the start of the array? What am I missing here.
Cheers!
When you use %s format in fscanf, it is expected that the argument is a char* that can hold the characters being read from the stream. That explains the warning message.
In your case, &word has the same numerical value as &word[0]. However, that is not true all the time. For example, if you have:
char* word = malloc(20);
then, the numerical value&word is not equal to that of&word[0]. The compiler is not taking the responsibility for dealing with such distinctions. It is simply expecting a char* as the argument.

warning: assignment makes integer from pointer without a cast ARGV

This is the warning I get.
copyit.c: In function ‘main’:
copyit.c:15: warning: assignment makes integer from pointer without a cast
copyit.c:16: warning: assignment makes integer from pointer without a cast
The lines of code that this corresponds to are the ones that begin with pointers (*).
char source[128],target[128],buffer[512];
if(argc==3) {
*source = argv[1];
*target = argv[2];
}
I just want to assign those two things so I can pass them from the command line like that and I can then use them in my handle (ex: inhandle=open(source,O_RDONLY);
Thank you.
argv is an array of string pointers. You should just change source and target to char * or const char * instead of arrays and change the code to
source = argv[3];
target = argv[4];
That will make it work. It will also prevent a buffer overflow had you copied the strings into the arrays. It would also mean your app will handle long file paths.
Use strcpy() from string.h:
strcpy(source,argv[1]);
strcpy(target,argv[2]);

Extracting string from main() arguments

I am trying to create a pointer to one of the main() arguments in my program.
I set up the initial pointer, then I set it equal to the 2nd element in the array, but I get an error when I try to compile, segmentation fault. Does this occur because a pointer is pointing to a bad address?
Here is the code:
char *filename;
*filename = argv[1];
printf("The filename is: %s", *filename);
I get errors about the pointer trying to cast the argument as an int. Is this because the pointer is actually an integer address value and I am trying to set it equal to a string?
Edit: When I change to "filename = argv[1]", then I get the following error from my compiler: assignment discards qualifiers from pointer target type.
A segmentation fault couldn't possibly occur when you compile. Unless, well, the compiler violates memory safety, which is unlikely. I'll take it that it happens when you run the program :D.
The problem is here:
*filename = argv[1];
It should be:
filename = argv[1];
Why? You declared a pointer to char, unitialized, poiting nowhere in particular. Then, you dereferenced that pointer and assigned data to that memory position. Which is, well, who knows where!
Edit: you also dereference filename in the printf() call. Remove that * :).
Also, didnt' the compiler shoot a warning when you assigned *filename? Making integer from pointer without a cast, would be my guess? Pay attention to the warnings, they provide useful information!
Cheers.
You're not making filename point to the same place as argv[1]. To do that you need
filename = argv[1];
With your version (*filename = argv[1];) you're trying to make whatever filename points to have the value that is in argv[1]. There's lots of stuff wrong with this: a) filename is not initialized and can point anywhere, even invalid locations; b) argv[1] is of type char* and you're trying to put it into a location of type char!
In the statement *filename = argv[1];, the expression *filename attempts to dereference (find the value pointed to) the filename pointer, which is not yet pointing anywhere meaningful.
Change the assignment to filename = argv[1].
You're dereferencing the char* when you try to assign it, so you're trying to stuff a pointer into a char. And since filename is uninitialized, you're trying to hit some random address (or perhaps address 0x00000000. And your print statement, if you got that far, wouldn't work either: you're again dereferencing the char* (to get a char) and then telling printf to interpret that as a pointer to a nul-terminated string.
Try this:
char *filename ;
filename = argv[1] ;
printf( "The filename is: %s" , filename ) ;

Resources