2015-12-23 4 views
2

Предположим, что у меня есть массив строк, который выглядит так: Alphabet Как вы можете видеть, это алфавит, представленный символом #. Цель программы - показать письмо (которое поступает от ввода) с помощью #.Получение одиночного символа из строкового массива в C

Таким образом, если вход = Е, я должен буду печатать E

Если письмо не beetwen [A-Z] или [A-Z], я должен напечатать знак вопроса (сделанный с #). Нам дается T: сообщение для кода H: высота буквы (количество строк), L: длина букв и ROW: последовательность строк, которые создают алфавит с #.

Так что я действительно получил часть уже закодированной программы. Но моя проблема заключается не в том, как разобраться в этом. Дело в том, что я только что узнал указатели (основное использование), и я не понимаю, как обращаться с ними в более сложном (для меня, это сложном) пути.

#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 

/** 
* Auto-generated code below aims at helping you parse 
* the standard input according to the problem statement. 
**/ 
int main() 
{ 
    int L; 
    scanf("%d", &L); fgetc(stdin); 
    int H; 
    scanf("%d", &H); fgetc(stdin); 
    char T[257]; 
    fgets(T, 257, stdin); 

    char elements[H][sizeof(T)]; 
    char *pointer, *Pelements[H]; 

    pointer = T; 

    for (int i = 0; i < H; i++) { 

     char ROW[1025]; 
     fgets(ROW, 1025, stdin); 
     // given by the program 

     strcpy(elements[i], ROW); 
     Pelements[i] = &elements[i]; 
     // now i got the address of every first character of a string 
    } 

    while(*pointer != '\0'){ 
     if(*pointer >='a' && *pointer <= 'z' || *pointer >='A' && *pointer <= 'Z'){ 
     int temp= ((*pointer) - 'A'); 
     if(temp <= 25){ 
      for(int i=0; i<H; i++){ 
      int index= temp*L; // getting the position where to start to print 
      for(int j=0; j<L; j++){ 
       printf("%s " , *Pelements+index); 
       Pelements[i]++; //could have used index++ 
      } 
      } 
     } 
     } 
     else{ 
      printf("?"); 
     } 
     pointer++; 
    } 
    return 0; 
} 

Программа не завершена (я не обработал [а-г]) на самом деле я пытаюсь использовать его только заглавными буквами.

ПРОБЛЕМА: Он продолжает возвращать «ошибку сегментации» или дает мне # в случайных позициях. Спасибо заранее.

+0

Что вы видите, когда вы кладете это в отладчике и шагнула код по одной строке за раз? Каковы были значения 'L' и' H'? – abelenky

+2

'strcpy (элементы [i], ROW)' копирует то, что может быть длиной до 1025 байт, в буфер из 257 байт; потенциального переполнения буфера. –

+0

H = 5 и L = 4. он несколько раз повторял ###. И фактически ### - первая строка E в ASCII. – Emanuele

ответ

1

Если я понял, что вы пытаетесь выполнить, большая часть вашего кода довольно бесполезна. Это:

#include <stdio.h> 
#include <stdlib.h> 

#define BUFSIZE 128 

int main() 
{ 

    char *ROW[5] = { 
     " # ## #### ###### ### #### ### ## # #### # ## # ## ###### ## ## ## ## ####### ", 
     "# ## ## # ## # # # # # ## ## #### ## ## ## ## ## # # ## ## ## ## # # # ", 
     "##### # # ### ## # #### # ### # #### ## ### # ### # # # ## #### # # # ## ", 
     "# # ### # ## # # ## # # # ## ## # ## ## ## ### # # # # ## ##### # # #  ", 
     "# ### #### #### #### #### # # ##### ## # # # ## ### # ### # # ## # # ### # ", 
    }; 
    const int L = 3; // why do you want to read those from stdin? 
    const int H = 5; // they depend on how you define your alphabet 
    const int not_a_letter = 26; // "index" of ? in your alphabet 
    const int space = 27;   // I added a space 
// char T[BUFSIZE]; 
// fgets(T, BUFSIZE, stdin); 
    char T[]= "Hello World!"; //better starting with something short. note what happens to the '!' 
    for(int i = 0; i < H; i++) { // for every row 
     char * pch = T; 
     int temp; 
     while(*pch != '\0') { 
      if(*pch >='A' && *pch <= 'Z') temp = *pch - 'A'; 
      else if (*pch >='a' && *pch <= 'z') temp = *pch - 'a'; // I'll print only capitals... 
      else if (*pch == ' ') temp = space; 
      else temp = not_a_letter; 
      int index = temp * L; 
      printf("%.*s " , L, ROW[i]+index); // print L char of string ROW[i] starting from index 
      pch++; 
     } 
     printf("\n"); 
    } 

    return 0; 
} 

Напечатает это:

# # ### # # #  # # # ## # ## ### 
# # # # # # #  # # # # # # # # # # 
### ## # # # #  ### # # ## # # # ## 
# # # # # # #  ### # # # # # # # 
# # ### ### ### #  # # # # # ### ## # 

редактировать:

Я хотел бы добавить некоторые соображения. Вход вашей программы считывается из stdin. Это требование, как я полагаю, поскольку большинство on-line компиляторов перенаправляют ввод и вывод из файлов, но не всегда удобно вводить каждый раз все переменные, особенно все эти «## #### ### ...» , поэтому я жестко закодировал их в программе. Я не добавлял лишних пробелов между буквами, чтобы мой L был 3, но в картине, которую вы опубликовали, так что ваш L равен 4.

Вы можете сохранить эту часть своей программы без изменений (в основном), но я Я хотел бы отметить пару вещей. Когда вы читаете T, вы выделяете достаточное пространство для 256 символов, обычно экран консолей имеет ширину ~ 80, поэтому строка, длина которой превышает 20 символов (80/4;), будет испорчена при печати на stdout, если выход не перенаправлен в файл (вероятно), или вы меняете программу, чтобы она могла распечатывать из T всего 20 символов за раз. Затем вы читаете «шрифт» с использованием буфера (ROW), достаточно большого, чтобы содержать 256 увеличенных символов (256 * 4 = 1024;), который представляет собой весь набор ASCII.Разумеется, я использовал только заглавные буквы, но проблема в том, что если они дают вам ВСЕГО персонажа, вам не нужна временная переменная, чтобы переместить индекс в нужный диапазон, иначе вам не нужно все это пространство. Вы должны проверить, в чем дело. Вы можете прочитать непосредственно в ROW после выделив память:

#define BUFSIZE 1025 

char **ROW = malloc(H*sizeof(char*)); 
for (int i = 0; i < H; i++) { 

    ROW[i] = malloc(BUFSIZE); 
    fgets(ROW[i], BUFSIZE, stdin); 

} 

Не забудьте освободить память перед закрытием программы:

for (int i = 0; i < H; i++) { 
    free(ROW[i]); 
} 
free(ROW); 
+0

Спасибо. Это именно то, чего я пытаюсь выполнить. Я понимаю, что мой процесс мышления идентифицирует меня как новичка. Есть несколько вещей, которые я не понимаю из-за отсутствия знаний. Например: в printf вы использовали «% * s» .. почему с *? Почему существуют две переменные, напечатанные для одной ссылки? (Есть только один% s, а L - int ..). Если вы спрашиваете себя, почему я пытаюсь прочитать некоторые переменные из stdin, причина в том, что это игра для программистов, и эти переменные уже имеют значение, заданное программистом. Еще раз спасибо, я ценю. – Emanuele

+0

@Emanuele: Вы можете использовать звездочку (*), чтобы передать спецификатор/точность ширины для printf(), а не жестко кодировать его в строку формата, так как я пропустил L (который не печатается). Я мог бы использовать «% .3s». –

+0

Я вижу, я уже знал, что можно использовать число, но я никогда не думал, что могу использовать переменную. Спасибо. – Emanuele

0

Я думаю, ваша проблема здесь:

int index = temp*L; 

Из кода temp может быть до 25 и в вашем входе в L является, например, символ A (64), ваш индекс будет 1600, который Я думаю больше, чем ваш размер Pelements.

Я не могу сказать, разрешит ли это вам всю вашу проблему, но это может заставить вас решить первую проблему.

+0

L, насколько велики буквы, указанные в ASCII, поэтому это должно быть правильно. Если длина буквы равна 4, temp * 4 вернет число, представляющее, где я должен начать печатать. – Emanuele