我知道之前已经多次询问过这个问题,但是我是C数组的完全初学者,并希望避免使用指针(如果可能的话)并尽可能保持简单。 我已经使用了用户输入的一个char数组,并希望删除程序中的任何重复的字符串值
#include<string.h>
#include<stdio.h>
int main(){
int N, i, j, k;
int flag=1;
scanf("%d", &N);
if(1<=N<=10^6){
char a[N][5];
for(i=0; i<N; i++){
scanf("%s", &a[i]);
}
for(i=0; i<N; i++){
for(j=i+1;j<N;){
if(strcmp(a[i],a[j])==0){
for(k=j+1; k<N; k++){
memcpy(a[k], a[k+1], 5);
}
N--;
}else{
j++;
}
}
}
for(i=0; i<N; i++){
printf("%s\n", a[i]);
}
}
return 0;
}
输入3和{“abc”,“abc”,“as”}仅返回值{“abc”}。 我想将数组作为{“abc”,“as”}。我无法理解代码或逻辑中的哪个地方,我出错了。
更新
我改变了下面提到的代码,但是对于更大的例子,它是连接字符串
#include<string.h>
#include<stdio.h>
int main(){
int N, i, j, k;
scanf("%d", &N);
if(1 <= N && N <= 1000000){
char a[N][5];
for(i=0; i<N; i++){
scanf("%5s", a[i]);
}
for(i=0; i<N; i++){
for(j=i+1;j<N;){
if(strcmp(a[i],a[j])==0){
for(k=j+1; k<N; k++){
strcpy(a[k-1], a[k]);
}
N--;
}else{
j++;
}
}
}
printf("%d\n", N);
for(i=0; i<N; i++){
printf("%s\n", a[i]);
}
}
return 0;
}
答案 0 :(得分:1)
以下是对评论中所有错误的描述:
#include<string.h>
#include<stdio.h>
int main(){
int N, i, j, k;
// check the return value!
if (scanf("%d", &N) != 1) return 1;
// if(1<=N<=10^6){
// this is completely wrong:
// 1. ^ doesn't mean "power" but bitwise exclusive or
// 2. 1<=N evaluates to 0 (false) or 1 (true), this is ALWAYS <= 10
// 3. so you have finally 1^6 = 7 -- ALWAYS true as a boolean
//
// what you want is:
if(1 <= N && N <= 1000000){
char a[N][5];
for(i=0; i<N; i++){
// scanf("%s", &a[i]);
// at least limit the number of characters read (one less
// than your buffer size because there's a 0 byte added)
// then, taking a *pointer* of an array is wrong, the array
// already decays as a pointer, so leave out the `&`
scanf("%4s", a[i]);
}
for(i=0; i<N; i++){
for(j=i+1;j<N;){
if(strcmp(a[i],a[j])==0){
for (k=j+1; k<N; k++){
// memcpy(a[k], a[k+1], 6);
// two errors here:
// 1. You only have 5 bytes per element, so copy only 5
// 2. this is *off by one* for the array index
// correct version:
memcpy(a[k-1], a[k], 5);
// (or use strcpy())
}
N--;
}else{
j++;
}
}
}
for(i=0; i<N; i++){
printf("%s\n", a[i]);
}
}
return 0;
}
通常,始终启用编译器警告。您的编译器会发现大部分这些错误,看看在使用gcc编译原始代码并启用警告时会发生什么:
$ gcc -std=c11 -Wall -Wextra -pedantic -o2darr 2darr.c
2darr.c: In function 'main':
2darr.c:8:12: warning: comparison of constant '10' with boolean expression is always true [-Wbool-compare]
if(1<=N<=10^6){
^~
2darr.c:8:9: warning: comparisons like 'X<=Y<=Z' do not have their mathematical meaning [-Wparentheses]
if(1<=N<=10^6){
~^~~
2darr.c:8:12: warning: suggest parentheses around comparison in operand of '^' [-Wparentheses]
if(1<=N<=10^6){
~~~~^~~~
2darr.c:11:21: warning: format '%s' expects argument of type 'char *', but argument 2 has type 'char (*)[5]' [-Wformat=]
scanf("%s", &a[i]);
^
2darr.c:11:21: warning: format '%s' expects argument of type 'char *', but argument 2 has type 'char (*)[5]' [-Wformat=]
2darr.c:6:13: warning: unused variable 'flag' [-Wunused-variable]
int flag=1;
^~~~
答案 1 :(得分:0)
我的第一反应是使用标准算法用c ++编写。
#include<iostream>
#include<string>
#include<algorithm>
#include<cmath>
#include<vector>
#include<unordered_set>
#include<algorithm>
template<class T, class A>
auto deduplictate_keep_order(std::vector<T, A> &vec) -> std::vector<T, A> &
{
std::unordered_set<T> seen;
seen.reserve(vec.size());
auto check_seen = [&seen](T const &val) {
return !seen.insert(val).second;
};
vec.erase(std::remove_if(vec.begin(), vec.end(), check_seen), vec.end());
return vec;
};
template<class T, class A>
auto deduplictate_any_order(std::vector<T, A> &vec) -> std::vector<T, A> &
{
std::sort(vec.begin(), vec.end());
vec.erase(std::unique(vec.begin(), vec.end()), vec.end());
return vec;
};
int main() {
int N, i, j, k;
int flag = 1;
std::cin >> N;
int limit = std::pow(10, 6);
if (1 <= N && N <= limit) { // 1 <= N <= will not do what you want. 10^6 is 10 XOR 6. You don't want that.
std::vector<std::string> a;
for (i = 0; i < N; i++) {
a.emplace_back();
std::cin >> a.back();
}
// remove duplicates
deduplictate_keep_order(a);
// or this
// deduplictate_any_order(a);
for (std::string const &s : a)
std::cout << s << '\n';
}
return 0;
}