Storing char in array with strcpy - c

char strr[10];
strcpy(strr, argv[1]);
This works fine for storing an entire argument but how do i use the same technique
if i want to store a certain char from the first argument.
strcpy(strr, argv[1][1]);
This wont work ofcourse since its a char, so im wondering how else i can do it
EDIT:
i just used char strr[10]; as an example of an char array. Please dont pay attention to the size of it.

You can't store a char in array using strcpy. strcpy is for strings - not chars.
But you can do it in another way.
It's very simple:
char strr[2] = { 0 }; // Make strr a string that can hold 1 char and a
// string termination. Initialize to zero.
strr[0] = argv[1][1]; // Copy the second char of the string pointed to by
// argv[1] to the first char of strr
Now sttr is a string that holds just one char (and the mandatory string termination).
Besides this code, you need to ensure that argv[1] is valid and that argv[1][1] is valid.
Something like:
char strr[2] = { 0 }; // Make strr a string that can hold 1 char and a
// string termination. Initialize to zero.
if (argc > 1 && strlen(argv[1]) > 1)
{
strr[0] = argv[1][1]; // Copy the second char of the string pointed to by
// argv[1] to the first char of strr
}

Related

Store a Char from command line to Char array in C

I'm having trouble when I try to store the stdin in a program inside char array variable.
It throws a segfault when it goes by these lines:
procNames[processNumber] = argv[1];
and
strcpy(procNames[processNumber], proc[0]);
How can I store the chars in the array procNames?
The usage is:
(stdin) <CHAR>: <NUMBER>
I want to store every <CHAR> and every <NUMBER> introduced by order. The <NUMBER> stores without erros, the <CHAR> storage throws the segmentation fault.
char line[80],proc[80];
// Storing
char procNames[80];
int procPorts[80];
// To iterate
int processNumber = 0;
int actualProcessNumber = 0;
[...]
for(;fgets(line,80,stdin);) {
sscanf(line,"%[^:]: %d",proc,&port);
[...]
if(strcmp(proc,argv[1]) == 0) {
if (repeatedProc == false) {
procNames[processNumber] = argv[1];
procPorts[processNumber] = puerto_udp;
actualProcessNumber = processNumber;
processNumber++;
}
} else {
if (repeatedProc == false) {
strcpy(procNames[processNumber], proc[0]);
procPorts[processNumber] = port;
processNumber++;
}
}
}
Can someone please help me?
Regarding the issues you get:
1.
You need
char procNames[N][80];
instead of
char procNames[80];
where N gives the amount of strings to hold in procNames. [80] - 1 just specifies the maximum amount of characters possible in each string.
2.
You cannot assign arrays with strings by the = operator in C. Use strcpy() instead.
Replace
procNames[processNumber] = argv[1];
with
strcpy( procNames[processNumber], argv[1] );
3.
strcpy(procNames[processNumber], proc[0]);
The second argument of needs to be a pointer to char, proc[0] is of type char. Use proc only.
proc has no string in it to copy. Use at least char proc[80] = ""; to not get a runtime error.
Your procNames is an array of characters, not an array of pointers. Arrays cannot be assigned, just copied, and procNames[processNumber] = argv[1] should actually issue a warning / an error.
Further, as you intend to have an array of - let's say - 10 such names, you probably mean
char procNames[10][80];
Then you can write
strcpy(procNames[processNumber],argv[1]);
to copy the contents of the string argv[1] points to.
Furhter, in order to avoid that you exceed the length of a procNames-entry, I suggest to use
strncpy(procNames[processNumber],argv[1],80);
You defined char procNames[80]; which means it's a string that can hold 80 characters (also counting the 0-terminator at the end).
Later one you're doing this procNames[processNumber] = argv[1]; where procNames[processNumber] points to a character and argv[1] is a string holding the first command line parameter. So in fact you're trying to assign a pointer to a char.
Your compiler must have at least warned you about this.
Make sure to really look at compiler output as it often tries to tell you what you are doing wrong.

geting each element of a textfile until ':' and store on struct variable

I need help :/
On textfile, I have something like this:
MyName: 15 3
and I want to read each element until ':' and store it in variable name of the struct, and read the next elements and store 15 and 3 in another variables.
typedef struct STRUCT_PLAYER{char name[20];
int sucess;
int numQuest;
int wrongs;} PLAYER;
int readTop(PLAYER playTop[]){
char *classify = "classificacao.txt";
FILE *fl;
fl = fopen(classify, "r");
char c;
int n=0;
if(cl==NULL){
printf("Error reading the file %s\n", classify);
exit(1);
}
else{
while(c!=EOF){
while(c!=':'){
c=getc(fl);
if(c!=':') playTop[n].name=c;
}
if(c==':')fscanf(fl, " %d %d\n", &playTop[n].numQuest, &playTop[n].wrongs);
n++;
}
}
return n;
this is my code, but it appears me an error, on this line
if(c!=':') playerTOP[n].nome=c;
error: assignment to expression with array type
but I don't understand what it is
c is char, playTop->name is a char[], so your are assigning incompatible types. Also
coderredoc answer
Array name is not a modifiable lvalue
When you initialize your structure do:
int n=0;
playTop[n].name[0] = 0;
...
while(c!=':'){
char cs[] = { getc(fl), 0 };
if(c!=':')
strcat(playTop[n].name, cs);
}
With this cs is a C-String containing one letter only and strcat appends
the string to playTop[n].name, thus saving the name
EDIT
Ricardo's comment
thank you. but I din't understant why you put a zero on char cs[] = { getc(fl), 0}
That is what I was talking about in the comment. In C a string must be
'\0'-terminated.
A C-String is a sequence of bytes. This sequence must end with the value 0.
Every value in the sequence represents a character based on the
ASCII encoding, for example the
character 'a' is 97, 'b' is 98, etc. The character '\0' has
the value 0 and it's the character that determines the end of the string.
That's why you hear a lot that C-Strings are '\0'-terminated.
In C you use an array of chars (char string[], char string[SOME VALUE]) to
save a string. For a string of length n, you need an array of dimension n+1, because
you also need one space for the terminating '\0' character.
When dealing with strings, you always have to think about the proper type,
whether your are using an array or a pointer. A pointer
to char doesn't necessarily mean that you are dealing with a C-String!
Let's take a look at
char str1[] = "Hallo";
char str2[] = { 'H', 'a', 'l', 'l', 'o', 0 };
Both declarations do the same thing, they initialized the arrays str1 and
str2 with 6 elements. str1[5] and str2[5] will be the same: 0 (or '\0'
in its char notation).
A string literal is the text that is wrapped in quotes, "Hello" is a string
literal. Somewhere in the memory of the process the linker puts the sequence
'H', 'a', 'l', 'l', 'o', 0 in memory, usually read-only memory (note the 0
at the end). Even though you don't write the '\0' explicitly, it will have
one.
The '\0' at the end of the sequence of chars is what makes the sequence a
C-String, not the type of the variable. If there is no '\0' at the end, it is not a C-String.
char cs[] = { getc(fl), 0};
is a shorthand of
char cs[2];
cs[0] = getc(fl);
cs[1] = '\0';
By doing the last assignments, I ensure that cs holds a C-String. Most
functions defined in string.h (standard library) expect C-Strings, so they
must be '\0'-terminated.
man strcat
#include <string.h>
char *strcat(char *dest, const char *src);
DESCRIPTION
The strcat() function appends the src string to the dest string,
overwriting the terminating null byte ('\0') at the end of dest, and
then adds a terminating null byte.
From the description you'll see that both dest and src must be strings,
thus '\0'-terminated. That's why I said you should initialize
playTop->name[0] with 0, so that is will be a valid (and empty) string. Only
then I can use strcat.
Luckily there are many ways to archive the same results. If you don't want to
use strcat you could do it also this way:
int name_idx = 0;
while(c!=EOF){
while(c!=':'){
c=getc(fl);
if(c!=':') playTop[n].name[name_idx++]=c;
}
if(c == ':')
{
// make sure that playTop[n].name is a c-string
playTop[n].name[name_idx] = 0;
fscanf(...);
}
...
}
One last thing:
It's not bad using an array for saving strings, the problem is that the
maximum length of the string is dimension or array - 1. In your case the
name must not be longer than 19 characters, otherwise you will have a buffer
overflow and you are going to write over memory that is not allocated for the
name, you will have undefined behaviour and anything could happen.
When you know that the max. length of your string won't pass certain value
(let's say 15), then it's fine to use char name[20]. If there's no guarantee
of a max. length, then you have to dynamically allocate memory for it using
malloc/realloc (and later you would have to free that memory).
Also, a better way to parse your line would be to use fgets to get the while
line and then parse it:
typedef struct STRUCT_PLAYER{char *name;
int sucess;
int numQuest;
int wrongs;} PLAYER;
int readTop(PLAYER playTop[]){
...
char line[1024];
fgets(line, sizeof line, fl);
int colon_index = strchr(line, ':');
// color_index is the index where : is in the line,
// the length of the name is colon_index - 1
// because you have to save \0 as well, you need to
// allocate one more space for the c-string
// name length + 1 ==> (colon_index - 1) + 1
// which equeals to colon_index
playTop[n].name = malloc(colon_index);
// copy the name from line into name. strncpy
// copies at most `colon_index - 1` characters, if
// \0 is not among them, it won't be appended at the end
// you have to do that
strncpy(playTop[n].name, line, colon_index - 1);
// making sure that name becomes a c-string
playTop[n].name[colon_index] = 0;
// sscanf is like fscan, only it takes the content from
// a string and not from a FILE object.
// line + colon_index + 1 ensures that sscanf reads only
// after the colon
sscanf(line + colon_index + 1, "...", ...);
}
Doing it this way, you ensure that the name can have any length. Note that
all these functions may fail: for example malloc might return NULL if
there is not enough memory, strchr might return NULL if a colon is not
found in the line (the line has a wrong format or is empty). The line itself could be
longer than 1024 bytes. For sake of simplicity I've omitted all those checks.
If you've understood my code, then you could make it better by checking for
the errors mentioned above. Read carefully the documentation of the functions
used here.
name is an array of characters and since you are copying character by character, need to use playTop[n].name[x]=c; since name is a character pointer doesn't make sense to compiler when you try to assign a character to it.
Array name is not a modifiable lvalue. You are assigning to it. Violating rules. That's why compiler complained. Even if it was modifiable you are having an incompatibility in type. Assigning a char to char[].
More logical would be to do this
playerTOP[n].nome[some_index]=c;
You have to store those characters in the nome member array of the struct.(which is a char array not char).
Also make int c and then do the check c!=EOF.
the whole, bug ridden:
while(c!=EOF){
while(c!=':'){
c=getc(fl);
if(c!=':') playTop[n].name=c;
}
if(c==':')fscanf(fl, " %d %d\n", &playTop[n].numQuest, &playTop[n].wrongs);
can be easily reduced (and should be reduced) to the clean:
while( 3 == fscanf( fl, " %19[^:]: %d %d",
playTop[n].name,
&playtop[n].numQuest,
&playTop[n].wrongs ) )
{
n++;
}

In C, I'm unable to copy a single element of an array of character strings to another string

I have a string "prompt" that holds a string of characters. The user must be able to change the prompt with user input, which I've collected and separated (using whitespace as a delimiter) into an array of char strings (tokens).
For example, assume:
char **tokens[2] = {"setprompt", "newprompt"};
char *prompt = "oldprompt";
if(strcmp(tokens[0], "setprompt") == 0)
{
strcpy(prompt, tokens[1]);
}
The strcmp() function works perfectly fine, however when it reaches strcpy(), the element in tokens[1] (which is the string "newprompt") isn't copied into the string prompt. This is my problem.
I've tried troubleshooting, in addition to using strncpy() instead but I think there's an issue somewhere with my declarations of each variable/pointer. Any assistance or ideas would be great.
Note: in my actual program, the tokens array doesn't have a definitive size of 2. This example is modified for simplicity. Thanks!
Your issue is this line:
char *prompt = "oldprompt";
It points to constant memory and cannot be modified (the way it is defined). Consider leaving it read-only and creating your own buffer instead for copying and modifying Something like:
#define MAX_STRING_SIZE 255
char *tokens[2] = {"setprompt", "newprompt"};
char *prompt = "oldprompt";
char myBuffer[MAX_STRING_SIZE];
strcpy(myBuffer, prompt );
if(strcmp(tokens[0], "setprompt") == 0)
{
strcpy(myBuffer, tokens[1]);
}

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.
}

Printing an array of characters

I have an array of characters declared as:
char *array[size];
When I perform a
printf("%s", array);
it gives me some garbage characters, why it is so?
http://www.cplusplus.com/reference/clibrary/cstdio/printf/
This url indicates printf takes in the format of: `int printf ( const char * format, ... );
#include <stdio.h>
#include <string.h>
#define size 20
#define buff 100
char line[buff];
int main ()
{
char *array[100];
char *sep = " \t\n";
fgets(line, buff, stdin);
int i;
array[0] = strtok(line, sep);
for (i = 1; i < size; i++) {
array[i] = strtok(NULL, sep);
if (array[i] == NULL)
break;
}
return 0;
}
You declare an array of characters like so:
char foo[size];
You seem to have it mixed up with char *, which is a pointer to a character. You could say
char *bar = foo;
which would make bar point to the contents of foo. (Or, actually, to the first character of foo.)
To then print the contents of the array, you can do one of the following:
// either print directly from foo:
printf("%s", foo);
// or print through bar:
printf("%s", bar);
Note, however, that C performs no initialization of the contents of variables, so unless you specifically set the contents to something, you'll get garbage. In addition, if that garbage doesn't happen to contain a \0; that is, a char with value 0, it will keep on outputting past the end of the array.
Your array is not initialized, and also you have an array of pointers, instead of an array of char's. It should be char* array = (char*)malloc(sizeof(char)*size);, if you want an array of char's. Now you have a pointer to the first element of the array.
Why are we making such a simple thing sound so difficult?
char array[SIZE];
... /* initialize array */
puts(array); /* prints the string/char array and a new line */
/* OR */
printf("%s", array); /* prints the string as is, without a new line */
The char in array after the end of what you want to be your string (ie. if you want your string to read "Hello" that would be the next char after the 'o') must be the terminating NUL character '\0'. If you use a C function to read input that would automatically be appended to the end of your buffer. You would only need to worry about doing it manually if you were individually writing characters to your buffer or something for some reason.
EDIT: As with pmg's comment, the '\0' goes wherever you want the string to end, so if you wanted to shorten your string you could just move it up closer to the front, or to have an empty string you just have array[0] = '\0';. Doing so can also be used to tokenise smaller strings inside a single buffer, just as strtok does. ie. "Part1\0Part2\0Part3\0". But I think this is getting away from the scope of the question.
ie. you wanted to store the first 3 chars of the alphabet as a string (don't know why anyone would do it this way but it's just an example):
char array[4];
array[0] = 'a';
array[1] = 'b';
array[2] = 'c';
array[3] = '\0';
printf("%s\n", array);
If you have something like char array[] = "Hello"; the '\0' is automatically added for you.
char *array[size];
array is not a char * with that, it's more like a char ** (pointer to an array of chars, with is similar to pointer to pointer to char).
If all you need is a C string, either:
char array[size];
and make sure you 0-terminate it properly, or
char *array;
and make sure you properly allocate and free storage for it (and 0-terminate it too).

Resources