Ваша getint()
функция ужасно хрупкая. Что сказать, пользователь вводит нецелое значение только один раз? При получении ввода определенного типа, как правило, лучше постоянно выполнять цикл, пока вы не получите действительный ввод (или пользователь не отменит ввод), и всегда защищать от ввода, который не соответствует ожидаемому (например, когда кошка наступает на клавиатуру). ...)
scanf
можно использовать, если используется правильно. Это означает, что вы несете ответственность за проверку возврата из scanf
каждый раз . Вы должны обработать три условия
(return == EOF)
пользователь отменил ввод, сгенерировав руководство EOF
, нажав Ctrl + d kbd> (или в окнах Ctrl + z kbd>, но см. CTRL + Z не генерирует EOF в Windows 10 (более ранние версии) ); (return < expected No. of conversions)
a соответствия [ 1122] или сбой входа . Для совпадения вы должны учитывать каждый символ, оставшийся в вашем входном буфере. (сканирование вперед во входном буфере с чтением и отбрасыванием символов до тех пор, пока не будет найдено '\n'
или EOF
); и, наконец, (return == expected No. of conversions)
, указывающий на успешное чтение - тогда вам нужно проверить, соответствует ли входные данные каким-либо дополнительным критериям (например, положительное целое число, положительная плавающая точка, в необходимом диапазоне и т. д.). ). Поместив это для работы с вашей функцией getint()
и передав строку символов, которая будет отображаться как приглашение пользователя (если не NULL
), вы можете сделать что-то похожее на:
int getint (int *value, const char *prompt)
{
/* loop continually until good input or canceled */
for (;;) {
int rtn; /* variable for return from scanf */
if (prompt) /* if not NULL */
fputs (prompt, stdout); /* display prompt */
rtn = scanf ("%d", value); /* attempt read */
if (rtn == EOF) { /* check for manual EOF */
fputs ("\n", stderr);
return 0;
}
empty_stdin(); /* all other cases - empty input buffer */
if (rtn == 1) /* good input, break */
break;
/* otherwise matching failure */
fputs (" error: invalid integer input.\n", stderr);
}
return *value; /* value also available through pointer */
}
[ 1132] ( примечание: значение, возвращаемое функцией, является проверкой того, была ли функция выполнена успешно (возврат 1
) или был ли пользователь отменен с помощью EOF
(возврат 0
) целочисленное значение становится доступным для вызывающей стороны через указатель value
)
Вспомогательная функция empty_stdin()
просто:
void empty_stdin (void)
{
int c = getchar();
while (c != '\n' && c != EOF)
c = getchar();
}
Есть много способов поставить getint()
вместе, чтобы адаптировать его к вашим потребностям, если вы правильно обрабатываете все три случая, описанные выше, вы можете делать это любым способом.
Это - вполне нежелательное решение, потому что оно взрывает число столбцов, в которых Вы нуждаетесь.
Для примера Ссылки/Узла выше, получающаяся схема базы данных была бы похожа на это:
SQL:
USE [GraphExample2]
GO
/****** Object: Table [dbo].[Node] Script Date: 02/26/2009 15:45:53 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[Node](
[NodeID] [int] IDENTITY(1,1) NOT NULL,
[NodeTypeDiscriminator] [int] NOT NULL,
[Name] [varchar](255) NOT NULL,
[Description] [varchar](1023) NULL,
CONSTRAINT [PK_Node] PRIMARY KEY CLUSTERED
(
[NodeID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
/****** Object: Table [dbo].[Link] Script Date: 02/26/2009 15:45:53 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[Link](
[LinkID] [int] IDENTITY(1,1) NOT NULL,
[LinkTypeDiscriminator] [int] NOT NULL,
[LeaderID] [int] NULL,
[FollowerID] [int] NULL,
[PersonID] [int] NULL,
[LocationID] [int] NULL,
[Name] [varchar](255) NULL,
[Description] [varchar](1023) NULL,
CONSTRAINT [PK_Link] PRIMARY KEY CLUSTERED
(
[LinkID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
/****** Object: ForeignKey [FK_Link_Node_Follower] Script Date: 02/26/2009 15:45:53 ******/
ALTER TABLE [dbo].[Link] WITH CHECK ADD CONSTRAINT [FK_Link_Node_Follower] FOREIGN KEY([FollowerID])
REFERENCES [dbo].[Node] ([NodeID])
GO
ALTER TABLE [dbo].[Link] CHECK CONSTRAINT [FK_Link_Node_Follower]
GO
/****** Object: ForeignKey [FK_Link_Node_Leader] Script Date: 02/26/2009 15:45:53 ******/
ALTER TABLE [dbo].[Link] WITH CHECK ADD CONSTRAINT [FK_Link_Node_Leader] FOREIGN KEY([LeaderID])
REFERENCES [dbo].[Node] ([NodeID])
GO
ALTER TABLE [dbo].[Link] CHECK CONSTRAINT [FK_Link_Node_Leader]
GO
/****** Object: ForeignKey [FK_Link_Node_Location] Script Date: 02/26/2009 15:45:53 ******/
ALTER TABLE [dbo].[Link] WITH CHECK ADD CONSTRAINT [FK_Link_Node_Location] FOREIGN KEY([LocationID])
REFERENCES [dbo].[Node] ([NodeID])
GO
ALTER TABLE [dbo].[Link] CHECK CONSTRAINT [FK_Link_Node_Location]
GO
/****** Object: ForeignKey [FK_Link_Node_Person] Script Date: 02/26/2009 15:45:53 ******/
ALTER TABLE [dbo].[Link] WITH CHECK ADD CONSTRAINT [FK_Link_Node_Person] FOREIGN KEY([PersonID])
REFERENCES [dbo].[Node] ([NodeID])
GO
ALTER TABLE [dbo].[Link] CHECK CONSTRAINT [FK_Link_Node_Person]
GO
EDMX:
<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="1.0" xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx">
<!-- EF Runtime content -->
<edmx:Runtime>
<!-- SSDL content -->
<edmx:StorageModels>
<Schema Namespace="GraphModel.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2005" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns="http://schemas.microsoft.com/ado/2006/04/edm/ssdl">
<EntityContainer Name="GraphModelStoreContainer">
<EntitySet Name="Link" EntityType="GraphModel.Store.Link" store:Type="Tables" Schema="dbo" />
<EntitySet Name="Node" EntityType="GraphModel.Store.Node" store:Type="Tables" Schema="dbo" />
<AssociationSet Name="FK_Link_Node_Follower" Association="GraphModel.Store.FK_Link_Node_Follower">
<End Role="Node" EntitySet="Node" />
<End Role="Link" EntitySet="Link" />
</AssociationSet>
<AssociationSet Name="FK_Link_Node_Leader" Association="GraphModel.Store.FK_Link_Node_Leader">
<End Role="Node" EntitySet="Node" />
<End Role="Link" EntitySet="Link" />
</AssociationSet>
<AssociationSet Name="FK_Link_Node_Location" Association="GraphModel.Store.FK_Link_Node_Location">
<End Role="Node" EntitySet="Node" />
<End Role="Link" EntitySet="Link" />
</AssociationSet>
<AssociationSet Name="FK_Link_Node_Person" Association="GraphModel.Store.FK_Link_Node_Person">
<End Role="Node" EntitySet="Node" />
<End Role="Link" EntitySet="Link" />
</AssociationSet>
</EntityContainer>
<EntityType Name="Link">
<Key>
<PropertyRef Name="LinkID" />
</Key>
<Property Name="LinkID" Type="int" Nullable="false" StoreGeneratedPattern="Identity" />
<Property Name="LinkTypeDiscriminator" Type="int" Nullable="false" />
<Property Name="LeaderID" Type="int" />
<Property Name="FollowerID" Type="int" />
<Property Name="PersonID" Type="int" />
<Property Name="LocationID" Type="int" />
<Property Name="Name" Type="varchar" MaxLength="255" />
<Property Name="Description" Type="varchar" MaxLength="1023" />
</EntityType>
<EntityType Name="Node">
<Key>
<PropertyRef Name="NodeID" />
</Key>
<Property Name="NodeID" Type="int" Nullable="false" StoreGeneratedPattern="Identity" />
<Property Name="NodeTypeDiscriminator" Type="int" Nullable="false" />
<Property Name="Name" Type="varchar" Nullable="false" MaxLength="255" />
<Property Name="Description" Type="varchar" MaxLength="1023" />
</EntityType>
<Association Name="FK_Link_Node_Follower">
<End Role="Node" Type="GraphModel.Store.Node" Multiplicity="0..1" />
<End Role="Link" Type="GraphModel.Store.Link" Multiplicity="*" />
<ReferentialConstraint>
<Principal Role="Node">
<PropertyRef Name="NodeID" />
</Principal>
<Dependent Role="Link">
<PropertyRef Name="FollowerID" />
</Dependent>
</ReferentialConstraint>
</Association>
<Association Name="FK_Link_Node_Leader">
<End Role="Node" Type="GraphModel.Store.Node" Multiplicity="0..1" />
<End Role="Link" Type="GraphModel.Store.Link" Multiplicity="*" />
<ReferentialConstraint>
<Principal Role="Node">
<PropertyRef Name="NodeID" />
</Principal>
<Dependent Role="Link">
<PropertyRef Name="LeaderID" />
</Dependent>
</ReferentialConstraint>
</Association>
<Association Name="FK_Link_Node_Location">
<End Role="Node" Type="GraphModel.Store.Node" Multiplicity="0..1" />
<End Role="Link" Type="GraphModel.Store.Link" Multiplicity="*" />
<ReferentialConstraint>
<Principal Role="Node">
<PropertyRef Name="NodeID" />
</Principal>
<Dependent Role="Link">
<PropertyRef Name="LocationID" />
</Dependent>
</ReferentialConstraint>
</Association>
<Association Name="FK_Link_Node_Person">
<End Role="Node" Type="GraphModel.Store.Node" Multiplicity="0..1" />
<End Role="Link" Type="GraphModel.Store.Link" Multiplicity="*" />
<ReferentialConstraint>
<Principal Role="Node">
<PropertyRef Name="NodeID" />
</Principal>
<Dependent Role="Link">
<PropertyRef Name="PersonID" />
</Dependent>
</ReferentialConstraint>
</Association>
</Schema>
</edmx:StorageModels>
<!-- CSDL content -->
<edmx:ConceptualModels>
<Schema xmlns="http://schemas.microsoft.com/ado/2006/04/edm" Namespace="GraphModel" Alias="Self">
<EntityContainer Name="GraphModelContainer" >
<EntitySet Name="NodeSet" EntityType="GraphModel.Node" />
<EntitySet Name="LinkSet" EntityType="GraphModel.Link" />
<AssociationSet Name="PersonPersonToPerson_Leader" Association="GraphModel.PersonPersonToPerson_Leader">
<End Role="Person" EntitySet="NodeSet" />
<End Role="PersonToPerson" EntitySet="LinkSet" />
</AssociationSet>
<AssociationSet Name="PersonPersonToPerson_Follower" Association="GraphModel.PersonPersonToPerson_Follower">
<End Role="Person" EntitySet="NodeSet" />
<End Role="PersonToPerson" EntitySet="LinkSet" />
</AssociationSet>
<AssociationSet Name="Person_PersonToLocation" Association="GraphModel.Person_PersonToLocation">
<End Role="Person" EntitySet="NodeSet" />
<End Role="PersonToLocation" EntitySet="LinkSet" />
</AssociationSet>
<AssociationSet Name="Location_PersonToLocation" Association="GraphModel.Location_PersonToLocation">
<End Role="Location" EntitySet="NodeSet" />
<End Role="PersonToLocation" EntitySet="LinkSet" />
</AssociationSet>
</EntityContainer>
<EntityType Name="Node" Abstract="true">
<Key>
<PropertyRef Name="NodeId" />
</Key>
<Property Name="NodeId" Type="Int32" Nullable="false" />
<Property Name="Name" Type="String" Nullable="false" />
<Property Name="Description" Type="String" Nullable="true" />
</EntityType>
<EntityType Name="Person" BaseType="GraphModel.Node" >
<NavigationProperty Name="Leaders" Relationship="GraphModel.PersonPersonToPerson_Leader" FromRole="Person" ToRole="PersonToPerson" />
<NavigationProperty Name="Followers" Relationship="GraphModel.PersonPersonToPerson_Follower" FromRole="Person" ToRole="PersonToPerson" />
<NavigationProperty Name="Locations" Relationship="GraphModel.Person_PersonToLocation" FromRole="Person" ToRole="PersonToLocation" />
</EntityType>
<EntityType Name="Location" BaseType="GraphModel.Node" >
<NavigationProperty Name="Visitors" Relationship="GraphModel.Location_PersonToLocation" FromRole="Location" ToRole="PersonToLocation" />
</EntityType>
<EntityType Name="Link" Abstract="true">
<Key>
<PropertyRef Name="LinkId" />
</Key>
<Property Name="LinkId" Type="Int32" Nullable="false" />
<Property Name="Name" Type="String" Nullable="true" />
<Property Name="Description" Type="String" Nullable="true" />
</EntityType>
<EntityType Name="PersonToPerson" BaseType="GraphModel.Link" >
<NavigationProperty Name="Leader" Relationship="GraphModel.PersonPersonToPerson_Leader" FromRole="PersonToPerson" ToRole="Person" />
<NavigationProperty Name="Follower" Relationship="GraphModel.PersonPersonToPerson_Follower" FromRole="PersonToPerson" ToRole="Person" />
</EntityType>
<EntityType Name="PersonToLocation" BaseType="GraphModel.Link" >
<NavigationProperty Name="Person" Relationship="GraphModel.Person_PersonToLocation" FromRole="PersonToLocation" ToRole="Person" />
<NavigationProperty Name="Location" Relationship="GraphModel.Location_PersonToLocation" FromRole="PersonToLocation" ToRole="Location" />
</EntityType>
<Association Name="PersonPersonToPerson_Leader">
<End Type="GraphModel.Person" Role="Person" Multiplicity="1" />
<End Type="GraphModel.PersonToPerson" Role="PersonToPerson" Multiplicity="*" />
</Association>
<Association Name="PersonPersonToPerson_Follower">
<End Type="GraphModel.Person" Role="Person" Multiplicity="1" />
<End Type="GraphModel.PersonToPerson" Role="PersonToPerson" Multiplicity="*" />
</Association>
<Association Name="Person_PersonToLocation">
<End Type="GraphModel.Person" Role="Person" Multiplicity="1" />
<End Type="GraphModel.PersonToLocation" Role="PersonToLocation" Multiplicity="*" />
</Association>
<Association Name="Location_PersonToLocation">
<End Type="GraphModel.Location" Role="Location" Multiplicity="1" />
<End Type="GraphModel.PersonToLocation" Role="PersonToLocation" Multiplicity="*" />
</Association>
</Schema>
</edmx:ConceptualModels>
<!-- C-S mapping content -->
<edmx:Mappings>
<Mapping xmlns="urn:schemas-microsoft-com:windows:storage:mapping:CS" Space="C-S">
<Alias Key="Model" Value="GraphModel" />
<Alias Key="Target" Value="GraphModel.Store" />
<EntityContainerMapping CdmEntityContainer="GraphModelContainer" StorageEntityContainer="GraphModelStoreContainer">
<EntitySetMapping Name="LinkSet">
<EntityTypeMapping TypeName="IsTypeOf(GraphModel.Link)">
<MappingFragment StoreEntitySet="Link">
<ScalarProperty Name="Description" ColumnName="Description" />
<ScalarProperty Name="Name" ColumnName="Name" />
<ScalarProperty Name="LinkId" ColumnName="LinkID" />
</MappingFragment>
</EntityTypeMapping>
<EntityTypeMapping TypeName="IsTypeOf(GraphModel.PersonToPerson)">
<MappingFragment StoreEntitySet="Link" >
<ScalarProperty Name="LinkId" ColumnName="LinkID" />
<Condition ColumnName="LinkTypeDiscriminator" Value="1" />
</MappingFragment>
</EntityTypeMapping>
<EntityTypeMapping TypeName="IsTypeOf(GraphModel.PersonToLocation)">
<MappingFragment StoreEntitySet="Link" >
<ScalarProperty Name="LinkId" ColumnName="LinkID" />
<Condition ColumnName="LinkTypeDiscriminator" Value="2" />
</MappingFragment>
</EntityTypeMapping>
</EntitySetMapping>
<EntitySetMapping Name="NodeSet">
<EntityTypeMapping TypeName="IsTypeOf(GraphModel.Node)">
<MappingFragment StoreEntitySet="Node">
<ScalarProperty Name="Description" ColumnName="Description" />
<ScalarProperty Name="Name" ColumnName="Name" />
<ScalarProperty Name="NodeId" ColumnName="NodeID" />
</MappingFragment>
</EntityTypeMapping>
<EntityTypeMapping TypeName="IsTypeOf(GraphModel.Person)">
<MappingFragment StoreEntitySet="Node" >
<ScalarProperty Name="NodeId" ColumnName="NodeID" />
<Condition ColumnName="NodeTypeDiscriminator" Value="1" />
</MappingFragment>
</EntityTypeMapping>
<EntityTypeMapping TypeName="IsTypeOf(GraphModel.Location)">
<MappingFragment StoreEntitySet="Node" >
<ScalarProperty Name="NodeId" ColumnName="NodeID" />
<Condition ColumnName="NodeTypeDiscriminator" Value="2" />
</MappingFragment>
</EntityTypeMapping>
</EntitySetMapping>
<AssociationSetMapping Name="PersonPersonToPerson_Follower" TypeName="GraphModel.PersonPersonToPerson_Follower" StoreEntitySet="Link">
<EndProperty Name="Person">
<ScalarProperty Name="NodeId" ColumnName="FollowerID" />
</EndProperty>
<EndProperty Name="PersonToPerson">
<ScalarProperty Name="LinkId" ColumnName="LinkID" />
</EndProperty>
</AssociationSetMapping>
<AssociationSetMapping Name="PersonPersonToPerson_Leader" TypeName="GraphModel.PersonPersonToPerson_Leader" StoreEntitySet="Link">
<EndProperty Name="Person">
<ScalarProperty Name="NodeId" ColumnName="LeaderID" />
</EndProperty>
<EndProperty Name="PersonToPerson">
<ScalarProperty Name="LinkId" ColumnName="LinkID" />
</EndProperty>
</AssociationSetMapping>
<AssociationSetMapping Name="Person_PersonToLocation" TypeName="GraphModel.Person_PersonToLocation" StoreEntitySet="Link">
<EndProperty Name="Person">
<ScalarProperty Name="NodeId" ColumnName="PersonID" />
</EndProperty>
<EndProperty Name="PersonToLocation">
<ScalarProperty Name="LinkId" ColumnName="LinkID" />
</EndProperty>
</AssociationSetMapping>
<AssociationSetMapping Name="Location_PersonToLocation" TypeName="GraphModel.Location_PersonToLocation" StoreEntitySet="Link">
<EndProperty Name="Location">
<ScalarProperty Name="NodeId" ColumnName="LocationID" />
</EndProperty>
<EndProperty Name="PersonToLocation">
<ScalarProperty Name="LinkId" ColumnName="LinkID" />
</EndProperty>
</AssociationSetMapping>
</EntityContainerMapping>
</Mapping>
</edmx:Mappings>
</edmx:Runtime>
<!-- EF Designer content (DO NOT EDIT MANUALLY BELOW HERE) -->
<edmx:Designer xmlns="http://schemas.microsoft.com/ado/2007/06/edmx">
<edmx:Connection>
<DesignerInfoPropertySet>
<DesignerProperty Name="MetadataArtifactProcessing" Value="EmbedInOutputAssembly" />
</DesignerInfoPropertySet>
</edmx:Connection>
<edmx:Options>
<DesignerInfoPropertySet>
<DesignerProperty Name="ValidateOnBuild" Value="true" />
</DesignerInfoPropertySet>
</edmx:Options>
<!-- Diagram content (shape and connector positions) -->
<edmx:Diagrams>
<Diagram Name="GraphModel" ZoomLevel="114" >
<EntityTypeShape EntityType="GraphModel.Node" Width="1.5" PointX="5.875" PointY="1.375" Height="1.427958984375" />
<EntityTypeShape EntityType="GraphModel.Person" Width="1.5" PointX="5.875" PointY="3.25" Height="1.4279589843749996" />
<EntityTypeShape EntityType="GraphModel.Location" Width="1.5" PointX="7.75" PointY="4.625" Height="1.0992643229166665" />
<InheritanceConnector EntityType="GraphModel.Location">
<ConnectorPoint PointX="7.375" PointY="2.4176741536458342" />
<ConnectorPoint PointX="8.5" PointY="2.4176741536458342" />
<ConnectorPoint PointX="8.5" PointY="4.625" />
</InheritanceConnector>
<EntityTypeShape EntityType="GraphModel.Link" Width="1.5" PointX="2.875" PointY="1.375" Height="1.427958984375" />
<EntityTypeShape EntityType="GraphModel.PersonToPerson" Width="1.75" PointX="2.75" PointY="3.25" Height="1.2636116536458326" />
<InheritanceConnector EntityType="GraphModel.PersonToPerson" ManuallyRouted="false">
<ConnectorPoint PointX="3.625" PointY="2.802958984375" />
<ConnectorPoint PointX="3.625" PointY="3.25" />
</InheritanceConnector>
<InheritanceConnector EntityType="GraphModel.Person">
<ConnectorPoint PointX="6.625" PointY="3.4603483072916683" />
<ConnectorPoint PointX="6.625" PointY="3.25" />
</InheritanceConnector>
<EntityTypeShape EntityType="GraphModel.PersonToLocation" Width="1.875" PointX="0.75" PointY="4.625" Height="1.2636116536458326" />
<InheritanceConnector EntityType="GraphModel.PersonToLocation">
<ConnectorPoint PointX="2.875" PointY="2.4176741536458342" />
<ConnectorPoint PointX="1.65625" PointY="2.4176741536458342" />
<ConnectorPoint PointX="1.65625" PointY="4.625" />
</InheritanceConnector>
<AssociationConnector Association="GraphModel.PersonPersonToPerson_Leader">
<ConnectorPoint PointX="5.875" PointY="3.8818058268229163" />
<ConnectorPoint PointX="4.5" PointY="3.8818058268229163" />
</AssociationConnector>
<AssociationConnector Association="GraphModel.PersonPersonToPerson_Follower">
<ConnectorPoint PointX="5.875" PointY="3.5034029134114579" />
<ConnectorPoint PointX="4.5" PointY="3.5034029134114579" />
</AssociationConnector>
<AssociationConnector Association="GraphModel.Person_PersonToLocation">
<ConnectorPoint PointX="6.625" PointY="4.677958984375" />
<ConnectorPoint PointX="6.625" PointY="5.0078214863281243" />
<ConnectorPoint PointX="2.625" PointY="5.0078214863281243" />
</AssociationConnector>
<AssociationConnector Association="GraphModel.Location_PersonToLocation">
<ConnectorPoint PointX="7.75" PointY="5.40018798828125" />
<ConnectorPoint PointX="2.625" PointY="5.40018798828125" />
</AssociationConnector>
</Diagram>
</edmx:Diagrams>
</edmx:Designer>
</edmx:Edmx>
AoA!
EntityModelCodeGenerator создает отношение 0..1 ко многим между двумя таблицами, Сделайте это 1 ко многим .
В таком случае это может быть возможным решением.
С уважением! Салахуддин