C语言三步翻转法

我们先来看题目,这道题目来自于牛客网。

首先我们需要将整个字符串先翻转一边,但这样字符串里面的单词的顺序也就改变了,所以之后我们需要将翻转后的字符串进行局部翻转。

以"the sky is blue"为例。第一遍翻转后字符串变成了"eulb si yks eht"。

之后我们将其中的单词进行局部翻转,就能得到"blue is sky the"。

那我们就要将字符串拆分成一个一个单词,对每一个单词进行翻转。先对"eulb"进行处理,然后再对后面的单词处理。

接下来先看代码


#include<stdio.h>
#include <string.h>
#include <assert.h>
void revolve(char* p1, char* p2)
{
    assert(p1 && p2);
    while (p1 < p2)
    {
        char w = *p1;
        *p1 = *p2;
        *p2 = w;
        p1++;
        p2--;
    }
}
int main()
{
    char str[100];
    gets(str);
    int sz = strlen(str);
    revolve(str, str + sz - 1);
    char* p = str;
    while (*p)
    {
        char* start = p;
        while (*p != ' ' && *p != '\0')
        {
            p++;
        }
        revolve(start, p - 1);
        if (*p == ' ')
        {
            p++;
        }
    }
    printf("%s", str);
}

首先使用gets函数从键盘上读取一段字符串。gets函数会一直读取直到遇到'\n'。但不会将'\n'读入数组。然后写一个翻转函数revolve,revolve的参数设为两个char*的地址,使用指针来交换字符。

将字符串整体翻转后,接下来就是将每个单词分别翻转。使用*p作为循环的结束条件,当*p为'\0'时就会结束。每个单词之间都是以空格作为分界,所以当*p是空格时,就读完了一个单词。

接下来就是将这个单词的首字母地址和末尾地址传给revolve,将单词翻转过来。

这里传末尾地址时需要减一,因为此时这个地址指向的是空格。地址减一就是单词的最后一个字母。

后面的if语句用来判断*p指向的是不是空格,如果是则跳过此空格,如果是'\0',则不跳过,因为循环是用*p来决定是否继续循环,如果跳过了'\0'可能会有问题发生。

最后打印出翻转后的字符串就行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
#include <stdio.h> #include <stdlib.h> #include <string.h> void add(char *a, char *b, char *sum) //大数相加函数 { int i, j, k = 0, carry = 0, lena = strlen(a), lenb = strlen(b); for (i = lena - 1, j = lenb - 1; i >= 0 || j >= 0; i--, j--) //从低位到高位依次相加,不足位补0 { int x = i >= 0 ? a[i] - '0' : 0; int y = j >= 0 ? b[j] - '0' : 0; int s = x + y + carry; sum[k++] = s % 10 + '0'; carry = s / 10; } if (carry) //如果最高位有进位,将进位加到结果 sum[k++] = carry + '0'; sum[k] = '\0'; //字符串结尾 for (i = 0, j = k - 1; i < j; i++, j--) //将结果翻转 { char temp = sum[i]; sum[i] = sum[j]; sum[j] = temp; } } void multiply(char *a, char *b, char *result) //大数相乘函数 { int lena = strlen(a), lenb = strlen(b); if (lena < lenb) //保证a的位数大于等于b的位数 { char *temp = a; a = b; b = temp; int temp_len = lena; lena = lenb; lenb = temp_len; } if (lenb == 0) //如果有一个数为0,结果就为0 { result[0] = '0'; result[1] = '\0'; return; } if (lenb == 1) //如果b只有一位,直接按位乘 { int i, carry = 0, x = b[0] - '0'; for (i = lena - 1; i >= 0; i--) { int s = (a[i] - '0') * x + carry; result[i + 1] = s % 10 + '0'; carry = s / 10; } if (carry) //如果最高位有进位,将进位加到结果 result[0] = carry + '0'; else result[0] = '0'; result[lena + (carry ? 1 : 0)] = '\0'; //字符串结尾 return; } int i, j; char *a1 = (char *)malloc((lena / 2 + 1) * sizeof(char)); //将a分为两部分,a1为低位部分 char *a2 = (char *)malloc((lena - lena / 2 + 1) * sizeof(char)); //a2为高位部分 char *b1 = (char *)malloc((lenb / 2 + 1) * sizeof(char)); //将b分为两部分,b1为低位部分 char *b2 = (char *)malloc((lenb - lenb / 2 + 1) * sizeof(char)); //b2为高位部分 char *a1b1 = (char *)malloc((lena / 2 + lenb / 2 + 2) * sizeof(char)); //a1*b1 char *a2b2 = (char *)malloc((lena - lena / 2 + lenb - lenb / 2 + 2) * sizeof(char)); //a2*b2 char *temp1 = (char *)malloc((lena / 2 + lenb / 2 + 2) * sizeof(char)); //a1+a2和b1+b2的和 char *temp2 = (char *)malloc((lena / 2 + lenb / 2 + 2) * sizeof(char)); //(a1+a2)*(b1+b2)的差 for (i = 0; i < lena / 2; i++) //分割a a1[i] = a[i]; a1[i] = '\0'; for (i = lena / 2; i < lena; i++) a2[i - lena / 2] = a[i]; a2[i - lena / 2] = '\0'; for (i = 0; i < lenb / 2; i++) //分割b b1[i] = b[i]; b1[i] = '\0'; for (i = lenb / 2; i < lenb; i++) b2[i - lenb / 2] = b[i]; b2[i - lenb / 2] = '\0'; multiply(a1, b1, a1b1); //递归计算a1*b1 multiply(a2, b2, a2b2); //递归计算a2*b2 add(a1, a2, temp1); //计算a1+a2 add(b1, b2, temp2); //计算b1+b2 multiply(temp1, temp2, temp2); //递归计算(a1+a2)*(b1+b2) for (i = 0; i < lena; i++) //将(a1+a2)*(b1+b2)减去a1*b1和a2*b2的和 temp2[i] -= a1b1[i] + a2b2[i] - '0'; for (i = 0; i < lena / 2; i++) //将a1*b1左移两倍的位数 a1b1[lena - i] = a1b1[lena / 2 - i - 1]; for (i = lena / 2; i < lena; i++) a1b1[i] = '0'; a1b1[lena] = '\0'; add(a1b1, a2b2, result); //将a1*b1和a2*b2的和加上(a1+a2)*(b1+b2)减去a1*b1和a2*b2的和 add(result, temp2, result); free(a1); free(a2); free(b1); free(b2); free(a1b1); free(a2b2); free(temp1); free(temp2); } int main() { char a[1000], b[1000], result[2000]; printf("请输入两个大数:\n"); scanf("%s%s", a, b); multiply(a, b, result); printf("%s\n", result); return 0; }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值