在 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;
}