我正在尝试编写一个自定义import VueScript2 from 'vue-script2'
...
mounted() {
VueScript2.load('/static/js/jquery.js').then(function () {
VueScript2.load('/static/js/plugins.js')
})
}
,该自定义strcat
用参数\n
分隔,最后一个除外,并用\0
终止字符串。
它最多可以处理5个参数,但是如果我尝试传递第六个参数,则会得到奇怪的响应:
MacBook-Pro-de-Domingo% ./test ok ok ok ok ok
ok
ok
ok
ok
ok
MacBook-Pro-de-Domingo% ./test ok ok ok ok ok ok
ok
ok
ok
ok
ok
P/Users/domingodelmasok
这是我的自定义strcat
代码:
char cat(char *dest, char *src, int current, int argc_nb)
{
int i = 0;
int j = 0;
while(dest[i])
i++;
while(src[j])
{
dest[i + j] = src[j];
j++;
}
if(current < argc_nb - 1)
dest[i + j] = '\n';
else
dest[i + j] = '\0';
return(*dest);
}
更新:完整的调用功能:
char *concator(int argc, char **argv)
{
int i;
int j;
int size = 0;
char *str;
i = 1;
while(i < argc)
{
j = 0;
while(argv[i][j])
{
size++;
j++;
}
i++;
}
str = (char*)malloc(sizeof(*str) * (size + 1));
i = 1;
while(i < argc)
{
cat(str, argv[i], i, argc);
i++;
}
free(str);
return(str);
}
这是怎么了?
谢谢!
编辑:修复了错误。
答案 0 :(得分:1)
代码有很多问题:
sizeof (char) == 1
符合C标准。
cat()
要求目标是字符串(由\0
终止),但自身不附加(current >= argc_nb - 1
除外)。这是一个错误。
free(str); return str;
是一个无用后错误。如果您呼叫free(str)
,则str
中的内容将不可避免地丢失,无法访问。 free(str)
只需删除即可;在这里不合适。
C中的数组索引为0。但是,concator()
函数跳过第一个字符串指针(因为argv[0]
包含用于执行程序的名称)。这是错误的,并最终会使人绊倒。相反,让concator()
在数组中添加所有字符串,但是使用concator(argc - 1, argv + 1);
调用它。
可能还有更多,但在这一点上,我认为使用更合适的方法从头开始重写是可以的。
考虑以下join()
函数:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
char *join(const size_t parts, const char *part[],
const char *separator, const char *suffix)
{
const size_t separator_len = (separator) ? strlen(separator) : 0;
const size_t suffix_len = (suffix) ? strlen(suffix) : 0;
size_t total_len = 0;
size_t p;
char *dst, *end;
/* Calculate sum of part lengths */
for (p = 0; p < parts; p++)
if (part[p])
total_len += strlen(part[p]);
/* Add separator lengths */
if (parts > 1)
total_len += (parts - 1) * separator_len;
/* Add suffix length */
total_len += suffix_len;
/* Allocate enough memory, plus end-of-string '\0' */
dst = malloc(total_len + 1);
if (!dst)
return NULL;
/* Keep a pointer to the current end of the result string */
end = dst;
/* Append each part */
for (p = 0; p < parts; p++) {
/* Insert separator */
if (p > 0 && separator_len > 0) {
memcpy(end, separator, separator_len);
end += separator_len;
}
/* Insert part */
if (part[p]) {
const size_t len = strlen(part[p]);
if (len > 0) {
memcpy(end, part[p], len);
end += len;
}
}
}
/* Append suffix */
if (suffix_len > 0) {
memcpy(end, suffix, suffix_len);
end += suffix_len;
}
/* Terminate string. */
*end = '\0';
/* All done. */
return dst;
}
逻辑很简单。首先,我们找出每个分量的长度。请注意,separator
仅添加在各部分之间(因此发生parts-1
次),并且suffix
最终添加。
((string) ? strlen(string) : 0
惯用语的意思是“如果string
为非NULL,则strlen(0)
,否则为0
” 。我们这样做,因为我们允许使用NULL分隔符和后缀,但是strlen(NULL)
是未定义的行为。)
接下来,我们为结果分配足够的内存,包括长度不包括的字符串结尾NUL字符\0
。
要附加每个部分,我们保持结果指针完整无缺,而是使用临时end
指针。 (到目前为止,这是字符串的结尾。)我们使用循环,将下一部分复制到end
中。在第二部分和后续部分之前,我们在该部分之前复制分隔符。
接下来,我们复制后缀,最后是字符串结尾'\0'
。 (当然,返回指向字符串开头而不是结尾的指针很重要;这就是为什么我们保持dst
指向新的结果字符串,而end
指向该点的原因我们附加了每个子字符串。)
您可以从命令行使用以下main()
来使用它:
int main(int argc, char *argv[])
{
char *result;
if (argc < 4) {
fprintf(stderr, "\n");
fprintf(stderr, "Usage: %s SEPARATOR SUFFIX PART [ PART ... ]\n", argv[0]);
fprintf(stderr, "\n");
return EXIT_FAILURE;
}
result = join(argc - 3, (const char **)(argv + 3), argv[1], argv[2]);
if (!result) {
fprintf(stderr, "Failed.\n");
return EXIT_FAILURE;
}
fputs(result, stdout);
return EXIT_SUCCESS;
}
如果您将以上内容编译为例如example
(我使用gcc -Wall -O2 example.c -o example
),然后运行
./example ', ' $'!\n' Hello world
在Bash shell输出中
Hello, world!
(以换行符结尾)。正在运行
./example ' and ' $'.\n' a b c d e f g
输出
a and b and c and d and e and f and g
(再次以换行符结尾)。 $'...'
只是Bash惯用语,用于指定字符串中的特殊字符。 $'!\n'
在Bash中与"!\n"
在C中相同,$'.\n'
是C中".\n"
的Bash等效。
(删除部件之间的自动换行符,并允许使用字符串而不是仅使用一个char作为分隔符和后缀,这是有意的选择,其原因有两个。主要的原因是阻止任何人仅复制粘贴此内容作为第二种方法的答案,第二种方法是显示虽然听起来声音可能比仅使用单个字符更为复杂,但实际上它几乎不需要额外的代码;并且如果您考虑实际使用情况下,允许使用字符串作为分隔符会带来很多选择。)
上面的示例代码仅经过非常轻松的测试,并且可能包含错误。如果您发现任何问题,或者不同意我上面写的任何内容,请在评论中告知我,以便我进行检查并根据需要进行修复。