所以我所拥有的是我从fgets(str,x,stdin);获得的字符串(str)。 如果我写例如“ Hello World”,我希望能够在字符串中每个单词的前面添加一个字符。
要获取此“ Hello?World?”举个例子。我认为通过尝试以这种方式解决它,我自己变得更加困难:
add(char *s, char o, char c){
int i, j = 0;
for (i = 0; s[i] != '\0'; i++) {
if (s[i] != o) {
s[j] = s[i];
}
else {
s[j] = c;
}
j++;
}
}
add(str, ' ','?');
printf("\n%s", str);
这将读出没有空格的“ Hello?World”。现在,我看到此工作的唯一方法是将所有内容都移到第一个“?”之后一个同时向右移动,同时还将“ W”的位置设为空格和“?”在最后。但是对于更长的字符串,我看不到自己这样做。
答案 0 :(得分:2)
如果不能确保容纳字符串的缓冲区足够大,就不能安全地扩展带有更多字符的字符串。因此,让我们设计一个解决方案,计算需要多少个额外的字符,分配一个足以容纳该长度字符串的缓冲区,然后执行复制循环。然后将新字符串返回给调用者。
char* add(const char* s, char o, char c)
{
size_t len = strlen(s);
const char* str = s;
char* result = NULL;
char* newstring = NULL;
// count how many characters are needed for the new string
while (*str)
{
len += (*str== o) ? 2 : 1;
str++;
}
// allocate a result buffer big enough to hold the new string
result = malloc(len + 1); // +1 for null char
// now copy the string and insert the "c" parameter whenever "o" is seen
newstring = result;
str = s;
while (*str)
{
*newstring++ = *str;
if (*str == o)
{
*newstring++ = c;
}
str++;
}
*newString = '\0';
return result;
}
然后您要调用的代码如下:
char* newstring g= add(str, ' ','?');
printf("\n%s", newstring);
free(newstring);
答案 1 :(得分:1)
#include <stdio.h>
#include <string.h>
int main(void) {
char text[] = "Hello World";
for(char* word = strtok(text, " .,?!"); word; word = strtok(NULL, " .,?!"))
printf("%s? ", word);
return 0;
}
Success #stdin #stdout 0s 4228KB
Hello? World?
答案 2 :(得分:1)
知道到达插入新字符的位置时可用的存储量,可以检查新字符是否适合可用的存储,从当前字符到字符串末尾移到右侧并插入新字符,例如
#include <stdio.h>
#include <string.h>
#define MAXC 1024
char *add (char *s, const char find, const char replace)
{
char *p = s; /* pointer to string */
while (*p) { /* for each char */
if (*p == find) {
size_t remain = strlen (p); /* get remaining length */
if ((p - s + remain < MAXC - 1)) { /* if space remains for char */
memmove (p + 1, p, remain + 1); /* move chars to right by 1 */
*p++ = replace; /* replace char, advance ptr */
}
else { /* warn if string full */
fputs ("error: replacement will exceed storage.\n", stderr);
break;
}
}
p++; /* advance to next char */
}
return s; /* return pointer to beginning of string */
}
...
(注意:该字符串必须是可变的,而不是 string-literal ,并且必须为插入的字符提供额外的存储空间。如果需要传递 string-literal 或当前字符串中没有额外的存储空间,请按照@Selbie的回答进行复制)
将一个简短的示例与一个1024-char
缓冲区进行存储,您可以执行以下操作:
#include <stdio.h>
#include <string.h>
#define MAXC 1024
char *add (char *s, const char find, const char replace)
{
char *p = s; /* pointer to string */
while (*p) { /* for each char */
if (*p == find) {
size_t remain = strlen (p); /* get remaining length */
if ((p - s + remain < MAXC - 1)) { /* if space remains for char */
memmove (p + 1, p, remain + 1); /* move chars to right by 1 */
*p++ = replace; /* replace char, advance ptr */
}
else { /* warn if string full */
fputs ("error: replacement will exceed storage.\n", stderr);
break;
}
}
p++; /* advance to next char */
}
return s; /* return pointer to beginning of string */
}
int main (void) {
char buf[MAXC];
if (!fgets (buf, MAXC, stdin))
return 1;
buf[strcspn(buf, "\n")] = 0;
puts (add (buf, ' ', '?'));
}
使用/输出示例
$ ./bin/str_replace_c
Hello World?
Hello? World?
仔细研究一下,如果您有任何疑问,请告诉我。
答案 3 :(得分:0)
只是为了好玩,这是我的实现。它在O(n)时间内就地修改字符串。它假定char缓冲区足够大,可以容纳其他字符,因此取决于调用代码来确保这一点。
#include <stdio.h>
void add(char *s, char o, char c)
{
int num_words = 0;
char * p = s;
while(*p) if (*p++ == o) num_words++;
char * readFrom = p;
char * writeTo = p+num_words;
char * nulByte = writeTo;
// Insert c-chars, iterating backwards to avoid overwriting chars we have yet to read
while(readFrom >= s)
{
*writeTo = *readFrom;
if (*writeTo == o)
{
--writeTo;
*writeTo = c;
}
writeTo--;
readFrom--;
}
// If our string doesn't end in a 'c' char, append one
if ((nulByte > s)&&(*(nulByte-1) != c))
{
*nulByte++ = c;
*nulByte = '\0';
}
}
int main(int argc, char ** argv)
{
char test_string[1000] = "Hello World";
add(test_string, ' ','?');
printf("%s\n", test_string);
return 0;
}
程序的输出为:
$ ./a.out
Hello? World?