Упражнения для практики языка C (четвертая часть лета)

Вставьте сюда описание изображения


Предисловие

Скажи важные вещи три раза!
изучать! изучать! изучать!


1. Массив

Если определено int a[8];, следующее выражение не может представлять адрес элемента массива a[1] ( )
A: &a[0]+1
B: &a[1]
C:&a[0]+ +
D: а+1

Анализ вопроса:
D вариант a — это адрес первого элемента при вычислении. Добавьте 1, чтобы получить адрес a[1]. AB, очевидно, правильный. C вариант a[0] сначала объединяется с ++ для формирования выражения. Выражение не может быть правильным.При взятии адреса
будет выдано сообщение об ошибке.Ответ:
C


2. Указательная арифметика

Среди следующих опций оператор, который не может работать с двумя переменными-указателями одного и того же базового типа: ( )
A: +
B: -
C: =
D: ==

Анализ вопроса:
неверно А. Поскольку добавление двух адресов бессмысленно и может выходить за пределы, оговорено, что добавление указателей запрещено. Вариант B, вы можете найти
количество элементов одного типа данных между местами хранения двух элементов данных. Вариант C, присваивание, без проблем. Вариант D, оцените, совпадают ли два указателя. Ответ

:
A


3. Подсчитывайте общее количество кроликов каждый месяц.

Ссылка на вопрос: ссылка OJ
Вставьте сюда описание изображения

Анализ вопроса:
Ключом к этому вопросу является нахождение закономерности между числами. Если вы будете осторожны, вы обнаружите, что на самом деле это последовательность Фибоначчи. Число кроликов в n-м месяце на самом деле равно числу Фибоначчи n-1.
Вставьте сюда описание изображения
Вопрос ответ:

#include <stdio.h>
int main() {
    
    
    int n;
    while (scanf("%d", &n) != EOF) {
    
    
        int sum1=1;
        int sum2=1;
        if(n<=2)
            printf("%d",sum2);
        else{
    
    
            for(int i=0;i<n-2;i++){
    
    
                int temp=sum1+sum2;
                sum1=sum2;
                sum2=temp;
            }
        }
        printf("%d",sum2);
    }
    return 0;
}

4. Применение двойных указателей

Существует следующая функция, функция этой функции ( )

int fun(char *s)
{
    
    
    char *t = s;
    while(*t++);
    return(t-s);
}

A: Сравните размеры двух символов B: Вычислите количество байтов памяти, занимаемых строкой, на которую указывает s
C: Вычислите длину строки, на которую указывает s D: Скопируйте строку, на которую указывает s, в строку t

Анализ вопроса:
Цикл останавливается, когда *t равно 0, и в то же время t++, t, наконец, остановится в позиции после '\0' в конце строки. Поскольку указатель хвоста минус указатель головы, t равно слово, которое вся строка занимает в памяти. Число разделов, включая \0. Длина строки ответа c не включает последний
ответ на вопрос \0:
B.


5. Указатель решения

Результат вывода после запуска следующей программы: ( )

include <stdio.h>
int main()
{
    
    
    int a[] = {
    
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}, *p = a + 5, *q = NULL;
    *q = *(p+5);
    printf("%d %d\n", *p, *q);
    return 0;
}

A: Сообщение об ошибке после запуска B: 6 6 C: 6 11 D: 5 10

Анализ вопроса:
неправильно инициализировать указатель q значением NULL, а затем разыменовывать указатель q. Указатели NULL не могут быть разыменованы.
Вопрос-ответ:
А


6. Умный план

Ссылка на вопрос: ссылка OJ
Вставьте сюда описание изображения

Совет:
len(solution) = len(guess) = 4
решения и догадки содержат только четыре символа: «R», «G», «B» и «Y».

Анализ вопроса:
Обход двух массивов, подсчет количества догадок и количества псевдодогадок.Количество
догадок: Если позиции одинаковы и цветные символы одинаковы, счетчик количества догадок + 1.
Количество псевдо- догадок. догадки: цвета одинаковы, но в разных позициях. На этот раз вам нужно только удалить угаданную позицию и подсчитать количество каждого символа, появляющегося в двух массивах. Меньший из них - это количество псевдо-догадок для каждого цвета.Ответ на вопрос

:

int* masterMind(char* solution, char* guess, int* returnSize){
    
    
    *returnSize=2;
    static int arr[2]={
    
    0};
    arr[0] = 0; arr[1] = 0;//静态空间不会进行二次初始化因此每次重新初始化,可以使用memset函数
    int solu[26]={
    
    0};//26个字符位 solution 四种颜色数量统计
    int gue[26]={
    
    0};//26个字符位 guess 四种颜色数量统计
    for(int i=0;i<4;i++){
    
    
        if(solution[i]==guess[i])//位置和颜色完全一致则猜中数量+1
            arr[0]++;
        else{
    
    
            solu[solution[i]-'A']+=1;///统计同一位置不同颜色的两组颜色数量,伪猜中不需要对应位置相同,只需要有对应数量的颜色就行
            gue[guess[i]-'A']+=1;
        }
    }
    for(int i=0;i<26;i++){
    
    //在两个颜色数量统计数组中查看颜色数量,取相同位置较小的一方就是为猜中数量
        arr[1]+=(solu[i]<gue[i]?solu[i]:gue[i]);
    }
    return arr;
}

7. Сумма двух чисел

Ссылка на вопрос: ссылка OJ
Вставьте сюда описание изображения

Анализ вопроса:
Основной идеей этого вопроса является идея двойного обхода
, но необходимо внести соответствующие корректировки по условиям, чтобы не допустить потери времени.Ответ

на вопрос:

int* twoSum(int* numbers, int numbersLen, int target, int* returnSize ) {
    
    
    * returnSize=2;
    static int arr[2]={
    
    0};
    memset(arr, 0x00, sizeof(arr));//静态空间不会二次初始化,因此手动初始化
    for(int i=0;i<numbersLen;i++){
    
    
        if (numbers[i] > target)//一旦大于目标数,可以直接跳过
            continue;
        for(int j=i+1;j<numbersLen;j++){
    
    //配对的数直接从i+1开始,防止出现重复配对,造成时间浪费
            if(numbers[i]+numbers[j]==target){
    
    
                arr[0]=i+1;
                arr[1]=j+1;
                return arr;
            }
        }
    }
    * returnSize=0;
    return NULL;
}

8. Индекс массива

В следующем коде элемент массива, представленный *(p[0]+1), равен ( )

int a[3][2] = {
    
    1, 2, 3, 4, 5, 6}, *p[3];
p[0] = a[1];

A: a[0][1]
B: a[1][0]
C: a[1][1]
D:a[1][2]

Анализ вопроса:
p — массив указателей, p[0] = a[1]; здесь a[1] — имя массива второй строки двумерного массива, а имя массива представляет собой адрес первого элемента , a[1] — это адрес a[1][0], поэтому p[0] хранит адрес первого элемента во второй строке, p[0]+1 — это адрес второго элемента во второй строке. row, *(p[ 0]+1) — второй элемент во второй строке. Так что С прав.
Ответ на вопрос:
С


9. Указатель

Что касается указателей, какое из следующих утверждений является правильным [Множественный выбор] ( )
A: Любой указатель может быть преобразован в void *
B: void * может быть преобразован в любой указатель
C: Размер указателя составляет 8 байт
D: Хотя указатели эффективны и гибки, могут быть небезопасными

Разбор вопроса:
Вариант C. Сколько байт занимает указатель, зависит от платформы. Это 8 байт в 64-битной среде и 4 байта в 32-битной среде.
Вопрос-ответ:
ABD


10. В поисках вершин

Ссылка на вопрос: ссылка OJ
Вставьте сюда описание изображения
Вставьте сюда описание изображения
Вставьте сюда описание изображения

Анализ вопроса:
Дихотомическое мышление,
середина больше правой, и считается, что половина увеличивается справа налево, затем право продолжает приближаться к левому право = середина, будьте осторожны, чтобы не оказаться в середине 1, потому что это положение может быть пиковой точкой.
Пока середина меньше правой, это означает, что данные начинают уменьшаться, затем левая смещается вправо, левая=средняя+1; и как только позиция средней+1 больше правой, это означает, что Положение «mid+1» — это точка, в которой левая полуправая половина уменьшается справа налево, а правая полуправая увеличивается слева, и является пиковой точкой.

Вопрос ответ:

int findPeakElement(int* nums, int numsLen ) {
    
    
    //边界情况处理,1个元素前后都是负无穷 以及 0号位置大于1号位置,-1位置负无穷的情况
    if (numsLen == 1 || nums[0] > nums[1]) return 0;
    //末尾位置数据大于上一个位置数据,而nums[numsLen]负无穷的情况
    if (nums[numsLen - 1] > nums[numsLen - 2]) return numsLen - 1;
    int left = 0, right = numsLen - 1, mid;
    while (left < right) {
    
    
        mid = left + (right - left) / 2;
        if (nums[mid] < nums[mid + 1])//中间比右边小,意味着右边肯定有个峰值
            left = mid + 1;
        else //否则在左边包括当前位置肯定有个峰值
            right = mid;
    }
    return left;
}

11. Вторичный указатель

Пожалуйста, укажите на ошибки в следующей программе [Множественный выбор] ( )

void GetMemory(char **p, int num)
{
    
    
    if(NULL == p && num <= 0)//1
        return;
    *p = (char*)malloc(num);
    return;
} 
int main()
{
    
    
    char *str = NULL;
    GetMemory(&str, 80); //2
    if(NULL != str)
    {
    
    
        strcpy(&str, "hello"); //3
        printf(str); //4
    } 
    return 0;
}

А: 1 Б: 2 В: 3 Д: 4

Анализ вопроса:
Во-первых, если одна из двух ситуаций верна, то она будет возвращена или должна использоваться, но использовать И здесь неправильно. В инструкции GetMemory(&str,100); передается адрес str. В инструкции char*str=NULL; str инициализируется нулевым указателем, но переменная указателя str также имеет адрес, поэтому p в параметре char**p хранится адрес переменной-указателя str, поэтому после вызова функции GetMemory адрес динамически открытого пространства сохраняется в str. Память не освобождается после возврата функции, но это не приведет к программная ошибка, но приведет только к утечке памяти. Неправильно использовать &str в третьем месте. Вам следует использовать str напрямую. Это первый адрес пространства, на которое вы только что подали заявку, и его можно использовать для получения копии строки.
Ответ на вопрос:
АС


12. С прямым порядком байтов и прямым порядком байтов.

Каковы возможные выходные результаты следующего кода? [Множественный выбор] ( )

#include <stdio.h>
typedef union
{
    
    
    int a;
    struct
    {
    
    
        short b;
        short c;
    };
}X;
int main()
{
    
    
    X x;
    x.a = 0x20150810;
    printf("%x,%x\n", x.b, x.c);
    return 0;
}

А: 2015810 Б: 50810201 С: 8102015 Д:`20150810

Анализ вопроса:
Для 0x20150810
, если он хранится в режиме прямого порядка байтов: от младшего адреса к верхнему адресу: 20 15 08 10. Вывод от младшего адреса к верхнему адресу: 20 15 08 10. Если хранится в режиме прямого байта: от младшего адреса к верхнему адресу
: 10 08 15 20 Вывод от старшего адреса к младшему адресу: 08 10 20 15
Этот номер присваивается объединению xa в типе int и доступен отдельно как члены структуры b и c. Они получают 2 байта младшего адреса и 2 байты старшего адреса соответственно.2 байта, с прямым порядком байтов — 2015 и 810, с прямым порядком байтов — 810 и 2015.

Вставьте сюда описание изображения

Ответ на вопрос:
АС


13. Беззнаковые параметры

Какие ошибки или последствия возникнут после выполнения следующей программы? [Множественный выбор] ( )

#define MAX 255
int main()
{
    
    
unsigned char A[MAX], i;
for(i = 0; i <= MAX; i++)
A[i] = i;
return 0;
}

A: Массив выходит за пределы B: Бесконечный цикл C: Переполнение стека D: Утечка памяти

Анализ проблемы:
Индекс массива выходит за пределы: размер массива равен 255, но когда a[255] содержит 256 элементов, он выходит за пределы. Бесконечный цикл: это связано с тем, что размер переменной типа символов без знака находится в диапазоне 0–255, поэтому я никогда не может быть больше 255, что представляет собой бесконечный цикл. Утечка памяти. Временные переменные, созданные в стеке, должны автоматически освобождаться системой, поэтому проблем с утечкой памяти быть не должно. Переполнение стека: тип переполнения буфера. Переполнение стека происходит потому, что в серии языков C нет встроенного механизма проверки, гарантирующего, что данные, скопированные в буфер, не должны превышать размер буфера. Поэтому, когда данные достаточно велики, они переполняют диапазон буфера. Ответ на вопрос
:
АБ


Четырнадцать пар чисел

Ссылка на вопрос: ссылка OJ
Вставьте сюда описание изображения

Анализ вопроса:
предположим, что входные данные n=10, k=3;
когда y <=k, это означает, что результат любого числа по модулю y находится между [0, k-1], что не соответствует условиям.
Когда y = k+1=4, подходящие числа для x — 3,7.
Когда y = k+2=5, подходящие числа для x — 3,4,8,9.
Когда y = k+3=6. Когда , квалифицированными числами для x являются 3, 4, 5, 9, 10.
Когда y = k+n,
x меньше текущего значения y, а количество уточненных чисел: yk,
x больше, чем текущее значение y, меньше 2. В данных *y количество чисел, удовлетворяющих условиям, равно: yk чисел.Как видно
из предыдущего шага, в диапазоне целых чисел, кратных y, количество чисел которые удовлетворяют условиям для x, равны (n / y) * (y - k)
n / y представляет количество полных интервалов 0 ~ y, y - k представляет количество квалифицированных чисел в каждом интервале.
рассмотреть равно 6... В дальнейшем статистика частей, выходящих за пределы кратного интервала и превышающих n
n % y, - это количество чисел, превышающих полный интервал. Числа ниже k учитывать не нужно. Условия: n %y - (k-1).Здесь следует отметить, что числа за пределами полного интервала аналогичны 9.
Если количество чисел меньше k,
итоговая формула равна 0: (n/y)*(y - k) + ((n % y < k) ? 0, (n % y - k + 1));

Вопрос-ответ:

#include <stdio.h>
int main() {
    
    
    long n, k;
    while (scanf("%ld %ld", &n, &k) != EOF) {
    
    
        if (k == 0) {
    
    
            printf("%ld\n", n * n);//任意数对的取模结果都是大于等于0的
            continue;
        }
        long count = 0;
        for (long y = k + 1; y <= n; y++) {
    
    
            count += ((n / y) * (y - k)) + ((n % y < k) ? 0 : (n % y - k + 1));
        }
        printf("%ld\n", count);
    }
    return 0;
}

15. Перехват строки

Ссылка на вопрос: ссылка OJ
Вставьте сюда описание изображения

Вопрос ответ:

#include <stdio.h>
#include<string.h>
int main() {
    
    
    char str[1001]={
    
    0};
    int k;
    while (scanf("%s %d", str, &k) != EOF) {
    
    
        char*ptr1=str;
        char*ptr2=str+k-1;
        while(ptr1<=ptr2){
    
    
            printf("%c",*ptr1);
            ptr1++;
        }
    }
    return 0;
}

Существует более лаконичный метод
решения проблемы:
чтобы перехватить первые n символов строки, вам нужно всего лишь заменить данные в позиции n индекса массива на конец метки строки.

#include <stdio.h>
int main()
{
    
    
    char str[101];
    while(scanf("%s", str) > 0) {
    
    
        int n;
        scanf("%d", &n);
        str[n] = '\0';
        printf("%s\n", str);
    }
    return 0;
}

Подведем итог

Скажи важные вещи три раза!
успех! успех! успех!
Вот и все вопросы во время летних каникул!
Давайте вместе поприветствуем следующий этап обучения!

おすすめ

転載: blog.csdn.net/mdjsmg/article/details/132757744