Here I come, there I am.

 

Проблем: конзолен скрипт, който чете входни параметри от конзолата (с подсещащи съобщения). Понякога може да се избегне с подаването на аргументи при извикването на командата, но не винаги. При четенето някои от данните биват пропускани и променливите остават празни. В частния случай това са методите cin.getline() в C++ и nextLine() на класа Scanner в Java.

Примерен код на C++:

#include <iostream>
 
using namespace std;
 
int main() {
    int number;
    char text1[100];
    char text2[100];
    cout << "Input number: " << endl;
    cin >> number;
 
    while (cin.get() != '\n');
    cout << "Input text 1: " << endl;
    cin.getline(text1, 100);
    cout << "Input text 2: " << endl;
    cin.getline(text2, 100);
 
    cout << "-----------------" << endl;
    cout << "Output:: \nNumber: " << number << endl <<
	"Text1: " << text1 << endl <<
	"Text2: " << text2 << endl;
 
    return 0;
}
 
 

Изход:

Очевидно първият символен низ след числото се прескача, а потребителят има възможност да оперира само със следващите променливи.

Причината е начинът на четене на метода. Тъй като cin e входният буфер на данни, променливата number извлича първото число, което е подадено от потребителя във входния буфер, като останалото си остава в буфера. Повторното ползване на "cin >>" ще игнорира последвалия вход в буфера и щом стигне до терминиращ символ (\n), ще започне четенето след него.

cin.getline() обаче работи малко по-различно. Той не игнорира останалата информация в буфера, а я прочита до стигане на терминиращия символ за нов ред. Тъй като след предходното четене задължително остава такъв символ, то първата употреба на getline() не прекъсва изпълнението за изчакване на вход от потребителя, а прочита последните входни данни и продължава изпълнението.

При горния сорс имаме 3 променливи: number, text1 и text2. При първото четене въвеждаме "24". Реалната стойност на буфера е "24/n". В променливата се записва стойността 24, но в буфера остава символа за нов ред. Затова при първото използване cin.getline(text1, 100) започва четене от буфера до стигане на \n. Тъй като терминиращият символ е първият наличен в буфера, text1 променливата остава празна. Следващото четене cin.getline(text2, 100) попада на празен буфер и изчаква подаването на текст от потребителя.

Ако на първото четене въведем "24string", то в променливата number получава стойност 24, а в буфера остава "string\n". text1 автоматично ще приеме стойността "string", а text2 ще очаква символен низ, въведен от потребителя.

Примерни вход и изход за горния случай:

Аз поне имам 2 възможни разрешения на проблема. Първото е слагане на допълнителен getline(), който да не вземате предвид. Това може да е повторно извикване на cin.getline(text1,100) или използване на допълнителен празен буфер за целта.

По-чист вариант е прочитане на буфера до достигане на терминиращия символ. Или, иначе казано, след четенето на числото, добавяне на следния ред:

 
while (cin.get() != '\n');

Вариант е и използването на cin.ignore(), но аз лично не го ползвам.

При използване на някое от горните решения, четенето вече е достъпно и за трите променливи:

----

Java

По подобен начин стоят нещата и с класа Scanner в Java. Разликата е, че въвеждането на "24string" при извикване на nextInt() метода ще хвърли изключение, защото единствените възможни входни данни са числови такива. Въпреки това последвало извикване на nextLine() би върнало празен стринг, заради терминиращия символ (аналогично с по-горния случай)

Затова вариант е всичко да минава през nextLine() и да се преобразува към числов вид. За по-професионален резултат е добре да се прихваща и Runtime изключението, което би възникнало при четене на друго, освен число. Пример:

import java.util.Scanner;
 
public class Foo  {
	public static void main(String[] args) {
		Scanner console = new Scanner(System.in);
		int number = 0;
		String text1 = null;
		String text2 = null;
		try {
			number = Integer.parseInt(console.nextLine());
			text1 = console.nextLine();
			text2 = console.nextLine();
			System.out.println("---------");
			System.out.println("Number: " + number);
			System.out.println("Text1: " + text1);
			System.out.println("Text2: " + text2);
		}
		catch(NumberFormatException nfe) {
			System.err.println("Incorrect number!");
		}
	}
}

 

Share and Enjoy:
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • MySpace
  • Slashdot
  • Technorati
  • TwitThis
del.icio.us Digg DZone Facebook Google Google Reader Magnolia reddit SlashDot Technorati ReadMe.ru Dobavi.com Dao.bg Lubimi.com Ping.bg Pipe.bg Svejo.net Web-bg.com

Сходни постове:

  1. Топ 10 проблема при преговорите - дискусия Една диску
  2. Таговете или категориите в WordPress 3.0 не работят (Headspace fix) При update
  3. Модерното CV или LinkedIn интеграцията   Раб

Related posts brought to you by Yet Another Related Posts Plugin.

Comments

Leave a Reply