所以我有一个分配,如果字符在字符串中有重复,我应该删除它。现在它可以做到,但也会在最后打印出垃圾值。我不知道为什么会这样,所以任何帮助都会很好。 我也不确定如何打印出新字符串的长度。
这是我的main.c
文件:
#include <stdio.h>
#include <string.h>
#include "functions.h"
int main() {
char string[256];
int length;
printf("Enter char array size of string(counting with backslash 0): \n");
/*
Example: The word aabc will get a size of 5.
a = 0
a = 1
b = 2
c = 3
/0 = 4
Total 5 slots to allocate */
scanf("%d", &length);
printf("Enter string you wish to remove duplicates from: \n");
for (int i = 0; i < length; i++)
{
scanf("%c", &string[i]);
}
deleteDuplicates(string, length);
//String output after removing duplicates. Prints out trash values!
for (int i = 0; i < length; i++) {
printf("%c", string[i]);
}
//Length of new string. The length is also wrong!
printf("\tLength: %d\n", length);
printf("\n\n");
getchar();
return 0;
}
printf("%c", string[i]);
的输出打印出字符串末尾的垃圾值,这是不正确的。
deleteDuplicates函数在functions.c
文件中如下所示:
void deleteDuplicates(char string[], int length)
{
for (int i = 0; i < length; i++)
{
for (int j = i + 1; j < length;)
{
if (string[j] == string[i])
{
for (int k = j; k < length; k++)
{
string[k] = string[k + 1];
}
length--;
}
else
{
j++;
}
}
}
}
答案 0 :(得分:1)
有一种更有效率和更安全的方式来进行锻炼:
#include <stdio.h>
#include <string.h>
void deleteDuplicates(char string[], int *length)
{
int p = 1; //current
int f = 0; //flag found
for (int i = 1; i < *length; i++)
{
f = 0;
for (int j = 0; j < i; j++)
{
if (string[j] == string[i])
{
f = 1;
break;
}
}
if (!f)
string[p++] = string[i];
}
string[p] = '\0';
*length = p;
}
int main() {
char aux[100] = "asdñkzzcvjhasdkljjh";
int l = strlen(aux);
deleteDuplicates(aux, &l);
printf("result: %s -> %d", aux, l);
}
您可以在此处查看结果: http://codepad.org/wECjIonL
甚至可以在这里找到更精致的方式: http://codepad.org/BXksElIG
答案 1 :(得分:0)
C中的函数默认是按值传递,而不是按引用传递。因此,deleteDuplicates函数不会修改main函数的长度。如果修改函数以通过引用传递,则将修改您的长度。
以下是使用您的代码的示例。
函数调用将是:
deleteDuplicates(string, &length);
该功能将是:
void deleteDuplicates(char string[], int *length)
{
for (int i = 0; i < *length; i++)
{
for (int j = i + 1; j < *length;)
{
if (string[j] == string[i])
{
for (int k = j; k < *length; k++)
{
string[k] = string[k + 1];
}
*length--;
}
else
{
j++;
}
}
}
}
答案 2 :(得分:0)
您可以通过散列数组中的字符来实现O(n)
解决方案。
但是,发布的其他答案将帮助您解决代码中的当前问题。我决定向你展示一种更有效的方法。
您可以像这样创建一个哈希数组:
int hashing[256] = {0};
将数组中的所有值设置为0
。然后,您可以检查插槽是否有0
,这意味着该角色尚未被访问过。每次找到0
时,将字符添加到字符串中,并将该插槽标记为1
。这可以保证不会添加重复的字符,因为只有在找到0
时才会添加它们。
这是一种在任何地方都使用的常用算法,它将有助于提高代码的效率。
最好使用fgets
来读取用户的输入,而不是scanf()
。
这是我刚才写的一些修改过的代码,它显示了哈希的这个想法:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define NUMCHAR 256
char *remove_dups(char *string);
int main(void) {
char string[NUMCHAR], temp;
char *result;
size_t len, i;
int ch;
printf("Enter char array size of string(counting with backslash 0): \n");
if (scanf("%zu", &len) != 1) {
printf("invalid length entered\n");
exit(EXIT_FAILURE);
}
ch = getchar();
while (ch != '\n' && ch != EOF);
if (len >= NUMCHAR) {
printf("Length specified is longer than buffer size of %d\n", NUMCHAR);
exit(EXIT_FAILURE);
}
printf("Enter string you wish to remove duplicates from: \n");
for (i = 0; i < len; i++) {
if (scanf("%c", &temp) != 1) {
printf("invalid character entered\n");
exit(EXIT_FAILURE);
}
if (isspace(temp)) {
break;
}
string[i] = temp;
}
string[i] = '\0';
printf("Original string: %s Length: %zu\n", string, strlen(string));
result = remove_dups(string);
printf("Duplicates removed: %s Length: %zu\n", result, strlen(result));
return 0;
}
char *remove_dups(char *str) {
int hash[NUMCHAR] = {0};
size_t count = 0, i;
char temp;
for (i = 0; str[i]; i++) {
temp = str[i];
if (hash[(unsigned char)temp] == 0) {
hash[(unsigned char)temp] = 1;
str[count++] = str[i];
}
}
str[count] = '\0';
return str;
}
示例输入:
Enter char array size of string(counting with backslash 0):
20
Enter string you wish to remove duplicates from:
hellotherefriend
输出:
Original string: hellotherefriend Length: 16
Duplicates removed: helotrfind Length: 10