What I want to do is to iterate through the quote till the end of the quote/(*quote has nothing in it). Is my code valid?
char *quote = "To be or not to be, that is the question.";
for (quote = 0; *quote != NULL; quote++){
*quote = tolower(*quote);
}
You probably need another pointer to traverse the array, otherwise access to your original string will be lost.
And preferably only use NULL for pointers.
Don't use 0 as the initial value, unless you want to use indices instead (see below).
Doing char *quote = will simply make quote point to the read-only literal, instead of copying the string. Use char quote[] = instead.
char quote[] = "To be or not to be, that is the question.";
char *quotePtr;
for (quotePtr = quote; *quotePtr != '\0'; quotePtr++){
*quotePtr = tolower(*quotePtr);
}
Test.
Using indices:
char quote[] = "To be or not to be, that is the question.";
int i;
for (i = 0; quote[i] != '\0'; i++){
quote[i] = tolower(quote[i]);
}
Test.
Consider this as an expansion to the answer given by Dukeling
When you use
char *quote = "Hello World";
This makes a read-only string, means that you can't change its contents in a simpler way.
Here *quote points to 'H'
BUT, you cannot do *quote = 'A';
This will give you an error.
If you wish to make changes to the characters in a string, it is a good habit to use arrays.
char quote[] = "Hello World";
Here also *quote points to 'H'
BUT, in this case *quote = 'A' is perfectly valid.
The array quote will get changed.
You're reassigning quote in your for initializer, which is invalid and will cause an access-violation because you're dereferencing it in the *quote != NULL part.
Semantically NULL and '\0' are equivalent, but syntactically I'd prefer this. Note that by using this approach you keep a pointer to (the start of) the string.
wchar const_t* quote = L"To be or not to be, that is the question.";
for( wchar_t* c = quote; *c != '\0'; c++ ) {
*c = tolower( *c );
}
alternatively using an index:
wchar const_t quote[] = L"To be or not to be, that is the question.";
for( size_t i = 0; i < sizeof(quote); i++ ) {
quote[i] = tolower( quote[i] );
}
(note that the semantics of sizeof will change if the value of quote is not known at compile time)
Related
I've been giving an... interesting... task. I've been asked to modify a character array using a pointer.
I'm aware that:
*char = "something"; //is a literal and cannot be modified.
char[] = "something"; //can be modified
But what about:
main.c
------
static char* stringlist01[] =
{
"thiy iy a ytring",
"this is also a string, unlike the first string",
"another one, not a great one, and not really like the last two.",
"a third string!",
NULL,
};
int main()
{
int ret = 9999;
printf("////TEST ONE////\n\n");
ret = changeLetterInString(stringlist01[0]);
printf("Return is: %d\n\n", ret);
printf("Stringlist01[0] is now: %s\n", stringlist01[0]);
}
AND
changeLetterInString.c
----------------------
int changeLetterInString(char *sentence)
{
if (sentence != NULL)
{
// TODO
// Need to change "thiy iy a ytring"
// into "this is a string"
// and save into same location so
// main.c can see it.
}
success = 0; // 0 is Good
return success;
}
So far, I've tried:
for (char* p = sentence; *p; ++p)
{
if (*p == 'y')
{
*p = 's';
}
}
And I've tried:
sentence[0] = 't'
sentence[1] = 'h'
sentence[2] = 'i'
sentence[3] = 's' // and so on...
But neither work.
Any help and/or insight would be greatly appreciated.
There are subtle differences between the two notations:
char string[] = "Hello World";
// vs
char* string = "Hello World";
They look similar enough, right? However they are different. The first one is an array of characters, whereas the second one is a pointer to an array of characters.
By default, any string literal will always be const. No way around it. Trying to modify a string literal will usually result in a segfault.
Your code contains an array of pointers to an array of characters. Since you contain pointer references to constant string literals, you cannot modify them. In order to modify them, you need to convert them into an array instead, like how it's done in the first example. This will transform the string literal to an array of characters, that can be modified, rather than being a pointer to memory which cannot be modified.
char strs[][] = {
"Hello",
"World"
}; // transforms the string literals into character arrays
strs[0][0] = 'X'; // valid
Whereas this would not compile, and caused undefined behaviour
char* strs[] = {
"Hello",
"World",
};
strs[0][0] = 'X'; // trying to modify a pointer to a constant string literal, undefined
Let's say I have a char *str and I want to assign it characters one by time using using pointers and incrementing ?
I've done :
char *str;
char c = 'a';
*str++ = c;
But it doesn't work.
How can I do that ?
str is just a pointer. It doesn't point anywhere valid (especially not to some memory you could write to). A simple possibility would be to have it point to an array:
char buf[1024] = {0}; // room for 1024 chars (or 1023 + a 0 byte for a string)
char *str = buf;
char c = 'a';
*str++ = c;
char *str is a pointer to a char (or an array of chars), however, you never assigned it. As has been mentioned earlier a char * basically says "go there" but there is no there there, you never gave it a value. You first need to use malloc to create space to put things in. Here's an example
char *str = malloc(sizeof(char)*10) //allocate space for 10 chars
char c = 'a';
str[0] = c;
no error check was made to malloc which you should do in your own program. You can also do it as such
char str[10];
char c = 'a';
str[0] = c;
however with this method you will be restricted to 10 chars and you cannot change that amount, with the previous method you can use realloc to get more or less space in your array.
But it doesn't work.
char* str;
... is not initialized to anything, therefore dereferencing it is to undefined behaviour. If it where initialized, then in expression *str++ = c; str++ is a post-increment operator, which returns a copy of the pointer whilst incrementing the original. The effect is that the copy points to the previous, and therefore what is pointed to by the previous pointer is assigned c.
To which part that doesn't work are you referring?
EDIT:
As mentioned in one of the comments, a copy is not really returned but the value is increment in place after having been evaluated.
As a variable with automatic storage duration the pointer str has indeterminate value. If even it had the static storage duration its value would be NULL. So you may not use such a pointer to store data.
What you mean can look for example the following way
#include <stdio.h>
int main( void )
{
char s[11];
char *p = s;
while (p != s + sizeof( s ) / sizeof( *s ) - 1 ) *p++ = 'a';
*p = '\0';
puts(s);
return 0;
}
The program output is
aaaaaaaaaa
Here in the program the pointer p of the type char * is initialized by the address of the first character of the array s.
Thus this statement used in the loop
*p++ = 'a';
fills sequentially the array with the character 'a'.
The next example is more interesting
#include <stdio.h>
char * copy_string(char *dsn, const char *src)
{
for (char *p = dsn; (*p++ = *src++) != '\0'; )
{
// empty body
}
return dsn;
}
int main( void )
{
char *src = "Hi QBl";
char dsn[7];
puts(copy_string(dsn, src));
return 0;
}
The program output is
Hi QBl
Here is a demonstration of a function that copies one character array containing a string into another character array using pointers.
There is pointer to string let say: char *p = "abcdef"
I want to delete some of the chars.
Let say every second char, so i want to get *p="ace"
my algorithm is something like:
int i=1,j=1
for(;p != '\0';p++,i++)
if (i % 2 ==0)
*(p - j++)= *p
*(p-j)='\0'
This algorithm is find the every second char of course but not matter how I try to write the "delete" process or there are compilation errors or the string is unchanged.
I start to believe there is no way to solve that issue without any malloc help.
Again i need to do it on O(n) without any other STRINGS arrays.
p != '\0' should be *p != '\0'(or *p != 0 or *p).
i should be initialized to 0. (You are keeping the wrong ones.)
j should be initialized to 0. (Off by one error.)
j needs to be incremented each time p is incremented.
Your code would be more readable and less fragile if you avoided offsets relative to an unrelated pointer.
void filter_inplace(char* src) {
char* dst = src;
for (size_t i=0; src[i]; ++i) {
if (i % 2 == 0)
*(dst++) = src[i];
}
*dst = 0;
}
Alternative:
void filter_inplace(char* src) {
char* dst = src;
while (1) {
if (!*src) break;
*(dst++) = *(src++);
if (!*src) break;
src++;
}
*dst = 0;
}
Of course, you can't do the following because p points to read-only memory:
char* p = "abcdef"; # XXX Should be "const char*".
filter_inplace(p); # XXX Overwrites read-only memory.
You could do the following:
char p[] = "abcdef";
filter_inplace(p);
You could do the following:
char* p = strdup("abcdef");
filter_inplace(p);
free(p);
I start to believe there is no way to solve that issue without any malloc help. Again i need to do it on O(n) without any other STRINGS arrays.
Kind of true. At least it is true that it can't be done without another string. Even if you used malloc (or strdup) for getting memory I would still consider it another string.
So as long a you initialize the char pointer like:
char *p = "abcdef";
it can not be done. You can't change any character in the string "abcdef".
If the above code was changed to
char p[] = "abcdef";
you would be able to do what you a trying. But even this could be considered as using another string as you have both the initializer string and char array.
I am trying to remove the whitespace at the start of a string, I have the index of the first non whitespace character, so I tried to do this:
int firstNonWhitespace = ...;
char *line = ...;
char *realStart = line + firstNonWhiteSpace;
strcpy(line, realStart);
but got Abort Trap 6 when at runtime.
However it works if I copy the realStart string to a temporary string, and then copy the temporary string to line:
int firstNonWhitespace = ...;
char *line = ...;
char *realStart = line + firstNonWhiteSpace;
char *tstring = malloc(strlen(realStart) + 1);
strcpy(tstring, realStart);
strncpy(line, tstring, strlen(line));
free(tstring);
There are two problems with your code.
The source and destination in the call to strcpy() do overlap, which results in Undefined Behaviour.
It might well be the case that realStart points to some non-writeable area of memory.
The faster way is
line += firstNonWhiteSpace;
but that might have consequences for your memory management, in case that part of memory was dynamically allocated. Only do this if you know what you are doing.
int main()
{
char a[] = " hey";
int i = 0;
char *p = a;
while(a[i++] == ' ');
strcpy(p, p + i - 1);
printf("%s\n", a);
}
Your problem is likely that you are not allowed to modify string literals, i. e. the code
int main() {
int firstNonWhitespace = 3;
char *line = " foo";
char *realStart = line + firstNonWhiteSpace;
strcpy(line, realStart);
}
may or may not work depending on whether your platform protects against modifying the string literal " foo". Copying the string first is required by the language standard.
Also, since strcpy() is not guaranteed to work correctly on overlapping strings (you might get lucky, though), use memmove() to do the moving.
How do I convert a character to a string in C. I'm currently using c = fgetc(fp) which returns a character. But I need a string to be used in strcpy
To answer the question without reading too much else into it I would
char str[2] = "\0"; /* gives {\0, \0} */
str[0] = fgetc(fp);
You could use the second line in a loop with whatever other string operations you want to keep using chars as strings.
You could do many of the given answers, but if you just want to do it to be able to use it with strcpy, then you could do the following:
...
strcpy( ... , (char[2]) { (char) c, '\0' } );
...
The (char[2]) { (char) c, '\0' } part will temporarily generate null-terminated string out of a character c.
This way you could avoid creating new variables for something that you already have in your hands, provided that you'll only need that single-character string just once.
Using fgetc(fp) only to be able to call strcpy(buffer,c); doesn't seem right.
You could simply build this buffer on your own:
char buffer[MAX_SIZE_OF_MY_BUFFER];
int i = 0;
char ch;
while (i < MAX_SIZE_OF_MY_BUFFER - 1 && (ch = fgetc(fp)) != EOF) {
buffer[i++] = ch;
}
buffer[i] = '\0'; // terminating character
Note that this relies on the fact that you will read less than MAX_SIZE_OF_MY_BUFFER characters
I use this to convert char to string (an example) :
char c = 'A';
char str1[2] = {c , '\0'};
char str2[5] = "";
strcpy(str2,str1);
A code like that should work:
int i = 0;
char string[256], c;
while(i < 256 - 1 && (c = fgetc(fp) != EOF)) //Keep space for the final \0
{
string[i++] = c;
}
string[i] = '\0';
//example
char character;//to be scanned
char merge[2];// this is just temporary array to merge with
merge[0] = character;
merge[1] = '\0';
//now you have changed it into a string
This is an old question, but I'd say none of the answers really fits the OP's question. All he wanted/needed to do is this:
char c = std::fgetc(fp);
std::strcpy(buffer, &c);
The relevant aspect here is the fact, that the second argument of strcpy() doesn't need to be a char array / c-string. In fact, none of the arguments is a char or char array at all. They are both char pointers:
strcpy(char* dest, const char* src);
dest : A non-const char pointer
Its value has to be the memory address of an element of a writable char array (with at least one more element after that).
src : A const char pointerIts value can be the address of a single char, or of an element in a char array. That array must contain the special character \0 within its remaining elements (starting with src), to mark the end of the c-string that should be copied.
Here is a working exemple :
printf("-%s-", (char[2]){'A', 0});
This will display -A-
FYI you dont have string datatype in C. Use array of characters to store the value and manipulate it. Change your variable c into an array of characters and use it inside a loop to get values.
char c[10];
int i=0;
while(i!=10)
{
c[i]=fgetc(fp);
i++;
}
The other way to do is to use pointers and allocate memory dynamically and assign values.