C: передача массивов другому методу правильно - PullRequest
2 голосов
/ 15 января 2010
/*
 * PURPOSE
 *      Search if a string contains a string and print it out from there
 */
#include <stdio.h>

void searchHaystack(char cHaystack[], char cNeedle[]);
void showResult(int iOffset, char cHaystack[]);

int main() {
    // Declarations
    char cHaystack[50], cNeedle[50];

    // Input
    puts("Haystack:");
    gets(cHaystack);
    puts("Needle:");
    gets(cNeedle);

    // Call searcher
    searchHaystack(cHaystack, cNeedle);

    return 0;
}

void searchHaystack(char cHaystack[], char cNeedle[]) {
    // Declarations
    int iCntr, iCntr2, iFoundOffset;

    // Search the haystack for the first letter of the needle
    for (iCntr == 0; iCntr < 50 && cHaystack[iCntr] != '\0'; iCntr++) {
        if (cHaystack[iCntr] == cNeedle[0]) {
            iFoundOffset = iCntr;
            for (iCntr2 == 1; iCntr2 < 50 && (cHaystack[iCntr+iCntr2] == cNeedle[iCntr2] || cNeedle[iCntr2] == '\0'); iCntr2++) {
                if (cNeedle[iCntr2] == '\0') {
                    showResult(iFoundOffset, cHaystack);
                }
            }
        }
    }
}

void showResult(int iOffset, char cHaystack[]) {
    int iCntr;

    // Print the substring char by char
    for (iCntr == iOffset; iCntr < 50 && cHaystack[iCntr] != '\0'; iCntr++) {
        printf("%c", cHaystack[iCntr]);
    }
    printf("\n");
}

Глядя на мой отладчик, я заметил, что cHaystack [] и cNeedle [] не передаются в searchHaystack должным образом, поскольку сохраняется только первый символ. Как это исправить? Я еще не узнал об указателях.

Кроме того, я получаю это предупреждение на всех трех циклах:

заявление без эффекта

Что с этим?

Ответы [ 6 ]

2 голосов
/ 15 января 2010

На самом деле, передается весь массив, отладчик показывает только первый символ по умолчанию, потому что в C система не знает размер массива. Это то, что программа должна отслеживать. Поскольку вы используете строки, которые обычно заканчиваются нулем, попробуйте установить переменную наблюдения "(char *) cHaystack" (без кавычек) и посмотрите, что тогда показывает отладчик.

Кроме того, операторы присваивания должны иметь один знак =, а не двойной знак ==. Итак:

for (iCntr = 0; ...

Следует использовать, НЕ:

for (iCntr == 0; ...

То же самое с другими для циклов.

1 голос
/ 15 января 2010

Массивы не являются первоклассными объектами в C; когда вы передаете массив в качестве параметра функции, тип выражения массива неявно преобразуется из «массива N-элемента T» в «указатель на T», и его значение устанавливается так, чтобы оно указывало на первый элемент в массиве [ 1].

В контексте объявления параметра функции int a[] совпадает с int *a (но это верно только в контексте объявления параметра функции); Ваша функция searchHaystack получает два указателя на тип char, которые соответствуют первым элементам соответствующих массивов. Отладчик не показывает весь массив, потому что в контексте функции они не являются массивами.

Кроме того, НИКОГДА, НИКОГДА, НИКОГДА НЕ ИСПОЛЬЗОВАТЬ gets(). Когда-либо. Это будет вводить точку отказа в вашем коде. Используйте fgets() вместо этого. C не проверяет границы массивов. Если вы вызываете gets() для буфера размером 10 символов, а пользователь вводит 100 символов, gets() с радостью сохранит эти дополнительные 90 символов в памяти после буфера, что может привести к сбою чего-то важного и привести к сбою или хуже (переполнение буфера - это распространенный эксплойт для вредоносных программ; червь Моррис использовал вызов gets() в sendmail).

Предупреждение приходит от вас, используя == вместо = для назначения ваших счетчиков циклов.

  1. Исключением из этого правила являются случаи, когда выражение массива является операндом операторов sizeof или address-of (&), или когда массив является строковым литералом, используемым для инициализации другого массива в объявлении. .
1 голос
/ 15 января 2010

Значения передаются правильно, но ваши ожидания того, как ваш отладчик должен их отображать, неверны. Как уже упоминалось, в C. нет типа string. Вместо этого C использует char* переменные - указатели на символы; ваши char[] эквивалентны char*.

Вы знаете, что указательный символ является первым символом в более длинной строке, но отладчик - нет. Он отображает символ, на который указывает указатель - который вы знаете, является первым из более длинной строки. Отладчик, однако, знает только, что это char*, и на него нужно указать char, поэтому он показывает, что char.

1 голос
/ 15 января 2010

Вы запускаете цикл с iCntr == 0 Это сравнение, поэтому не устанавливает iCntr на ноль.

Использовать iCntr = 0 (один знак равенства)

1 голос
/ 15 января 2010

Это массивы символов, а не строки. В C строка имеет тип char *, и вы должны выделить память для них.

Конечно, когда вы говорите varname [5], это то же самое, что сказать * (varname + 5)

В основном вам нужно узнать об указателях для использования строк в C.

EDIT

Как указано ниже (и мной выше), вы можете использовать массивы символов, такие как строки в C. ОДНАКО, я хочу сказать, что если вы не узнаете немного об указателях, у вас будут большие проблемы. 1011 *

Например:

  • Невозможно просмотреть строку в отладчике.

  • Не помещать ноль в качестве последнего символа в массиве и иметь сумасшедшие случайные ошибки

  • Забывая, что вы выделили только X байтов для массива и переходя через конец

и т.д.

Если вы не понимаете, как работают указатели в C, это действительно сложно - если не невозможно работать с языком.

Полагаю, проф расскажет об этом на следующей неделе.

0 голосов
/ 15 января 2010

Предупреждение, вероятно, вызвано

iCntr == 0,iCntr2 == 1, iCntr == iOffset

Полагаю, вы собирались:

iCntr = 0,iCntr2 = 1, iCntr = iOffset

Что касается прохождения массивов, вы можете сделать что-то вроде (используя указатели):

void searchHaystack(char* cHaystack, int cHaystackSize, char* cNeedle, int cNeedleSize )
...
  for (iCntr = 0; iCntr < cHaystackSize && cHaystack[iCntr] != '\0'; ++iCntr )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...