2014-11-16 1 views
0

제 질문을 보내 주셔서 감사합니다! (이제 해결되었습니다!) :)초심자 C 프로그램 - 아나그램 프로그램에서 루프의 필요한 출력을 반환하려면 어떻게해야합니까? (해결됨!)

C (나는 아직 초보자이고 책/노트를 통해 배우고 있음)에서 교과서 샘플 연습을 통해 실습 프로그램을 만드는 연습을하고 있습니다. 사용자가 입력 한 두 개의 문자열이 대/소문자 또는 간격과 상관없이 아나그램입니다. 내 프로그램이 컴파일되지만 사용자가 두 번째 문자열을 입력 할 수 있도록 첫 번째 getString 프롬프트를 지나지 않는 이유는 무엇입니까? 여기 연습 문제와 내가 지금까지 작성한 코드 (하단)입니다.

알고리즘 제 문자열을 읽은 후 각 문자 보지 한 몇 번 카운트 26 int 배열을 사용하는 루프 물품. 두 번째 문자열을 읽습니다. 이번에는 int 배열의 각 문자 수를 줄입니다. int 배열의 모든 단일 요소가 0이면 문자열이 anagram입니다. 문자가 아닌 문자는 무시하십시오. 대문자는 소문자 인 과 동일하게 취급하십시오. 이에 대한 도움말이 아래에 나와 있습니다.

필요한 기능 다음 기능을 사용해야합니다. 적절한 매개 변수 과 반환 유형을 설계해야합니다. 프로그램이 더 간단 해지고 하고 더 명확 해지면 다른 기능을 추가 할 수도 있습니다.

main() 변수를 선언 한 다음 아래에 설명 된 함수를 호출하여 문제를 해결합니다.

초기화() 첫 번째 문자열을 읽기 전에 모든 char 및 int 배열의 내용을 지 웁니다. 찾는

에는 getString() 를 프롬프트 (. 널 문자 '\ 0'숯 배열 내의 각 요소를 설정)로부터 입력 된 문자열을 판독한다. 이렇게하면 표준 라이브러리 함수 gets()가 호출됩니다. 함수 프로토 타입은 다음과 같습니다. char * gets (char s []); 문자열 s에 다음 입력 행을 읽습니다. 그것은 종결 개행 문자를 '\ 0'으로 대체합니다. s 또는 파일 끝나 오류가 발생하면 NULL을 반환합니다.

setLetters() 첫 번째 문자열의 모든 문자를 통해 루프, 을하고, int 배열에서 해당 문자의 수를 업데이트합니다. 이렇게하면 에서 다음과 같은 표준 라이브러리 함수를 호출하십시오.함수 프로토 타입은 다음과 같습니다

INT의 isalpha에 (숯불 C) 문자 c가 나 소문자 대문자 문자가있는 경우 반환이 아닌 제로 (참)

문자 tolower를 (숯불 C) 경우 문자 c는 대문자이며 해당 소문자를 반환합니다. 그렇지 않으면 두 번째 문자열의 모든 문자 위에

checkLetters() 루프 c를 반환하고 int 배열 해당 문자에 대한 카운트는 1 감산한다. setLetters()와 매우 비슷합니다.

isZero() int 배열에 대한 루프. 모든 요소가 0이면 TRUE를, 그렇지 않으면 FALSE를 반환합니다.

이 내가 작성하고 편집 한 코드가 지금 완벽하게 작동된다

#include <stdio.h> 
#include <ctype.h> // to include isalpha() and tolower() 
#define LEN 100 // maximum length of array input 
#define ABC 26 // amount of letters from A to Z starting from 0 


/* lab5.c: Compares user input to determine if they are anagrams */ 
void initialize(char s1[], char s2[], int count[]); // clears string and count arrays for new user input 
void getString(char s[]); // reads user input using gets() 
void setLetters(char s1[], int count[]); // increments count with input from first string 
void checkLetters(char s2[], int count[]); // decrements count with input from second string 
void isZero(int count[]); // inspects count value to determine whether strings were anagrams 

int main() { 

    char string1[LEN]; 
    char string2[LEN]; 
    int count1[ABC] = {0}; // initilaize the 26 elements in count to 0 

    while (1 == 1) { // while (true), aka infinite loop 

     initialize(string1, string2, count1); 

     getString(string1); // read the first string 
     setLetters(string1, count1); // count how many times a letter has been seen 
     getString(string2); // read the second string 
     checkLetters(string2, count1); // decrement each letter's count from the value generated by first string 

     isZero(count1); // determine whether the second string letter count decremented completely 
    } 
} 
void initialize(char s1[], char s2[], int count[]) { 
    int i; // counter variable 

    for (i = 0; s1[i] != '\0'; i++) { // for every element in string1 
     s1[i] = '\0'; // replace it with a null character 
     count[i] = 0; // set the value to 0 to clear 
    } 
    for (i = 0; s2[i] != '\0'; i++) { // for every element in string2 
     s2[i] = '\0'; // replace it with a null character 
    } 
} 
void setLetters(char s1[], int count[]) { 
    int i = 0; // counter variable 

    for (i = 0; s1[i] != '\0'; i++) { // for each character in string1 
     if (isalpha(s1[i])) { // if value is a letter 
     count[tolower(s1[i]) - 'a']++; // convert it to lowercase; subtract 'a' from it 
     // increment the count of that index in count array 
     } 
    } 
    return count; // not sure if I need this, but keeping it just in case... 
} 
void checkLetters(char s2[], int count[]) { 
    int i; // counter variable 

    for (i = 0; s2[i] != '\0'; i++) { // for each character in string2 
     if (isalpha(s2[i])) { // if value is a letter 
     count[tolower(s2[i]) - 'a']--; // convert it to lowercase; subtract 'a' from it 
     // decrement the count of that index in count array 
     } 
    } 
    return count; // not sure if I need this, but keeping it just in case... 
} 
void getString(char s[]) { 

    printf("Enter the string: "); // prompts user for string input 
    gets(s); // reads input into the string, terminates with null character 
    // I read that gets() is not widely used anymore because of "serious security issues"... 
    // so people recommend using fgets(), getline(), or scanf() instead. 
    // What are your thoughts on this? :) 
} 
void isZero(int count[]) { 
    int i; // counter variable 
    int x = 0; // variable to track if there's a FALSE value 

    for (i = 0; i < ABC; i++) { // for every element in the count array 
     if (count[i] != 0) // if there are any values that were not decremented by the second string 
      x = 1; // return FALSE 
    } 
    if (x == 1) { // if count array is not completely "empty" 
     printf("Not Anagram\n\n"); // FALSE: the words are not anagrams 
    } 
    else { // otherwise... 
     printf("Anagram\n\n"); // TRUE: the words match, yay! 
    } 
} 

출력 :

Enter the string: Mattress 
Enter the string: Smartest 
Anagram 

... 그리고 그게 내가 필요 정확히입니다! : D

+1

오늘이 질문을하지 않았습니까? – Rizier123

+2

코드에 몇 가지 문제가 있습니다. 그것은 첫번째 장소에서 컴파일해서는 안됩니다. 'setLetters'는'int'를 반환하도록 선언되었지만'int'에 대한 포인터를 반환합니다. 'initialize'는'char' (왜 ???)를 반환하도록 선언되었지만 아무것도 리턴하지 않습니다. 'getString'은 할당에 배치 된 프로토 타입과 다른 프로토 타입을가집니다. –

+0

'setLetters()'와'checkLetters()'내부의 루프는 루프 본문의 끝에서 'i'를 증가시켜야합니다. 이제는 무한 루프가됩니다. – Dmitri

답변

1

죄송합니다. 지난밤에 getString 함수를 바꾸기위한 예를 게시하려고합니다. 다음은 fgetsinput의 간단한 예제입니다. stdin에서 입력을 받아 fgets을 사용하면 코드의 보안/취약성이 크게 향상됩니다. 스택에서 정적으로 생성 된 저장소를 사용할 때는 읽는 가장 큰 입력 행 (또는 문자열)을 나타내는 상수 인 #define이 정상입니다. 아래에서 읽을 최대 문자열 크기는 처음에 256으로 정의 된 상수 MAXS입니다. 필요에 따라 조정할 수 있습니다. 참고또한

128 사이 2048, 당신은 null-terminating 문자가 입력 항상null-terminated 않는 것이라고 보장과 문자열을 작성하는 모든 제로 (NULL)에 저장 문자열을 초기화하여 일반적으로 참조 값의 정상 범위 당신은 MAXS-1에 마지막으로 널 (null)을 덮어 :

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

#define MAXS 256 

char *fgetsinput (char *s) 
{ 
    fgets (s, MAXS - 1, stdin);  /* read string from stdin */ 

    size_t len = strlen (s);  /* calculate length   */ 

    if (s[len-1] == '\n')   /* if last char is newline */ 
     s[len-1] = 0;    /* set to null-terminator */ 

    return s;      /* return adds flexibility */ 
} 

int main (void) { 

    char line[MAXS] = {0};     /* initialize to zero (null) */ 

    while (strcmp (line, "quit") != 0) 
    { 
     printf ("\n enter a string : "); 
     fgetsinput (line);     /* return not used in this call */ 
     printf (" string in line : %s\n", line); 
    } 

    printf ("\n enter a string to assign to pointer : "); 

    char *p = fgetsinput (line);   /* return assinged to pointer */ 
    printf (" What is the value pointed to by 'p'? : %s\n\n", p); 

    return 0; 
} 

출력 :

$ ./bin/getinputex 

    enter a string : A string for fgets to read. 
    string in line : A string for fgets to read. 

    enter a string : quit 
    string in line : quit 

    enter a string to assign to pointer : A string for fgets to read and assign. 
    What is the value pointed to by 'p'? : A string for fgets to read and assign. 

함수는 함수에 대한 인수 중 하나로 파일 설명자를 전달하여 파일 스트림에서 쉽게 읽을 수 있도록 확장 될 수 있습니다. (예 : char *fgetsinput (char *s, FILE *fp)). 그런 다음 함수에서 stdinfp으로 바꾸고 열린 파일 스트림에서 읽을 수 있습니다.

+0

귀하의 모든 제안에 감사드립니다 David! 운동 지침에 따라 정확한 결과를 출력하도록 코드를 업데이트했습니다. :) – paulalucai

+0

좋습니다. 많은 영리한 사람들이 도와 드리겠습니다. 앞으로 C를 배우면서 핵심은 단순히 느려지는 것입니다. C는 '정확한'언어입니다. 이것은 훌륭한 자산이자 하드웨어에 대한 낮은 수준의 제어를 제공하는 언어의 요구 사항입니다. 각 문장의 각 부분이 중요합니다. 다른 언어는 'close-enough'이라는 광범위한 구문을 허용 할 수 있습니다. C를 사용하면 '올바른'또는 '잘못된'것입니다. C를 배우는 약간의 추가 시간은 잘 소비 된 시간입니다. –

+0

예 가끔은 언어가 "정확하다"는 방식과 모든 것을 수동으로 계산해야하는 것처럼 느껴집니다. 나는 지혜의 말씀을 따를 것이다. 고마워! 멋진 데이비드 데이비드를 보내십시오! :) – paulalucai

관련 문제