在 C 中使用字符串的每个第 k 位循环问题
Every k-th digit cyclic problem using strings in C
给定一些字符串形式的数字,我想从中提取每个第 k 个数字。然后我遍历剩余的字符串并再次提取每个第 k 个数字。我得到的结果应该是这些提取的数字(按正确的顺序)形成的数字。示例:123456789,k = 3 --> 369485271
我的算法如下:虽然字符串的长度允许提取每个第 k 个数字,但我遍历该字符串并将每个第 k 个元素存储在另一个字符串中。然后我通过跟踪元素的正确索引从原始字符串中删除提取的元素,并在我的 str 的长度足够时继续前进。
我不知道我的代码有什么问题。也许我的方法不是很好,有一些 better/simpler 方法可以解决这个问题?
#include <stdio.h>
#include <string.h>
void remove(char *str, unsigned int index) {
char *src;
for (src = str+index; *src != '[=10=]'; *src = *(src+1),++src) ;
*src = '[=10=]';
}
int main() {
char number[100];
char result[100];
int k;
printf("Enter a string: ");
scanf("%s",number);
printf("Enter a key: ");
scanf("%d",&k);
while (strlen(number)>k-1) {
for (int i = 0, p = 0; number[i] != '[=10=]'; i++) {
if (i % k == (k-1)) {
result[p] = number[i];
p++;
}
}
for (int j = 0; number[j] != '[=10=]'; j++){
if (j % k == (k-1)) {
remove(number, j);
j+=1; /*since the index was shifted due to removing an element*/
}
}
}
puts(result);
return 0;
}
下面的代码似乎是你想要的:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void remove_(char *str, unsigned int index) {
char *src;
for (src = str+index; *src != '[=10=]'; *src = *(src+1),++src) ;
*src = '[=10=]';
}
int main(int argc, const char * argv[]) {
char number[100];
char result[100];
int tmp[100];
int k;
printf("Enter a string: ");
scanf("%s",number);
printf("Enter a key: ");
scanf("%d",&k);
int p = 0;
for (int tp = 0; strlen(number) > k-1; tp = 0) {
for (int i = 0; number[i] != '[=10=]'; i++)
if (i % k == (k-1))result[p++] = number[i];
for (int j = 0; number[j] != '[=10=]'; j++)
if (j % k == (k-1)) tmp[tp++] = j;
for (; tp; --tp) remove_(number, tmp[tp-1]);
}
// The newly added code
for (int index; strlen(number); ) {
index = (k-1) % strlen(number);
result[p++] = number[index];
remove_(number, index);
}
puts(result);
return 0;
}
最重要的是,每一次while循环,都需要一次性把number
中的元素去掉。在确保您原始代码的完整性的同时,我做了一些更改。不幸的是,原代码的主要思想是错误的。
一轮后应该从尾巴(包括其余部分)循环到头部。但是我发现你提供的代码的作用是,每一轮结束后,下一轮从头部的第0个元素开始。
顺便说一句,你的算法类似于Josephus problem
你有些问题:
- 您在
while
循环的每次迭代中再次从头开始编写输出。
- 您没有处理最后一位数字
- 您没有将输入视为循环输入。
- 你没有终止你的输出字符串。
remove
已经是标准库函数的名字了。
一个较短的版本可能是这个(未经测试):
#include <stdio.h>
#include <string.h>
void remove_digit(char *str, unsigned int index) {
char *src;
for (src = str+index; *src != '[=10=]'; *src = *(src+1),++src)
;
}
int main() {
char number[100];
char result[100];
int k;
printf("Enter a string: ");
scanf("%s",number);
printf("Enter a key: ");
scanf("%d",&k);
int p = 0;
int i = 0;
int skip = k-1; // We remove 1 digit and skip k-1 digits
while (number[0] != 0) {
i = (i + skip) % strlen(number);
result[p] = number[i];
p++;
remove_digit(number, i);
}
number[p] = 0;
puts(result);
return 0;
}
给定一些字符串形式的数字,我想从中提取每个第 k 个数字。然后我遍历剩余的字符串并再次提取每个第 k 个数字。我得到的结果应该是这些提取的数字(按正确的顺序)形成的数字。示例:123456789,k = 3 --> 369485271
我的算法如下:虽然字符串的长度允许提取每个第 k 个数字,但我遍历该字符串并将每个第 k 个元素存储在另一个字符串中。然后我通过跟踪元素的正确索引从原始字符串中删除提取的元素,并在我的 str 的长度足够时继续前进。 我不知道我的代码有什么问题。也许我的方法不是很好,有一些 better/simpler 方法可以解决这个问题?
#include <stdio.h>
#include <string.h>
void remove(char *str, unsigned int index) {
char *src;
for (src = str+index; *src != '[=10=]'; *src = *(src+1),++src) ;
*src = '[=10=]';
}
int main() {
char number[100];
char result[100];
int k;
printf("Enter a string: ");
scanf("%s",number);
printf("Enter a key: ");
scanf("%d",&k);
while (strlen(number)>k-1) {
for (int i = 0, p = 0; number[i] != '[=10=]'; i++) {
if (i % k == (k-1)) {
result[p] = number[i];
p++;
}
}
for (int j = 0; number[j] != '[=10=]'; j++){
if (j % k == (k-1)) {
remove(number, j);
j+=1; /*since the index was shifted due to removing an element*/
}
}
}
puts(result);
return 0;
}
下面的代码似乎是你想要的:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void remove_(char *str, unsigned int index) {
char *src;
for (src = str+index; *src != '[=10=]'; *src = *(src+1),++src) ;
*src = '[=10=]';
}
int main(int argc, const char * argv[]) {
char number[100];
char result[100];
int tmp[100];
int k;
printf("Enter a string: ");
scanf("%s",number);
printf("Enter a key: ");
scanf("%d",&k);
int p = 0;
for (int tp = 0; strlen(number) > k-1; tp = 0) {
for (int i = 0; number[i] != '[=10=]'; i++)
if (i % k == (k-1))result[p++] = number[i];
for (int j = 0; number[j] != '[=10=]'; j++)
if (j % k == (k-1)) tmp[tp++] = j;
for (; tp; --tp) remove_(number, tmp[tp-1]);
}
// The newly added code
for (int index; strlen(number); ) {
index = (k-1) % strlen(number);
result[p++] = number[index];
remove_(number, index);
}
puts(result);
return 0;
}
最重要的是,每一次while循环,都需要一次性把number
中的元素去掉。在确保您原始代码的完整性的同时,我做了一些更改。不幸的是,原代码的主要思想是错误的。
一轮后应该从尾巴(包括其余部分)循环到头部。但是我发现你提供的代码的作用是,每一轮结束后,下一轮从头部的第0个元素开始。
顺便说一句,你的算法类似于Josephus problem
你有些问题:
- 您在
while
循环的每次迭代中再次从头开始编写输出。 - 您没有处理最后一位数字
- 您没有将输入视为循环输入。
- 你没有终止你的输出字符串。
remove
已经是标准库函数的名字了。
一个较短的版本可能是这个(未经测试):
#include <stdio.h>
#include <string.h>
void remove_digit(char *str, unsigned int index) {
char *src;
for (src = str+index; *src != '[=10=]'; *src = *(src+1),++src)
;
}
int main() {
char number[100];
char result[100];
int k;
printf("Enter a string: ");
scanf("%s",number);
printf("Enter a key: ");
scanf("%d",&k);
int p = 0;
int i = 0;
int skip = k-1; // We remove 1 digit and skip k-1 digits
while (number[0] != 0) {
i = (i + skip) % strlen(number);
result[p] = number[i];
p++;
remove_digit(number, i);
}
number[p] = 0;
puts(result);
return 0;
}